LinearAllocator内存分配

简介:

在Android4.4中,在hwui将以前的绘制命令由原来的枚举类型,全部以类的形式呈现(一是为了便于扩展,二是由于加入延时渲染列表,不得不用类来实现),抽象类为DisplayListOp,在该类中重载了new的方法,即用了new placement的方式,统一分配内存,而不是每个操作自己分配,即用了LinearAllocator来管理每个操作需要申请的内存,这样能够提升申请内存的性能,同时能够便于统一管理。

class DisplayListOp {
public:
    // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
    // standard new() intentionally not implemented, and delete/deconstructor should never be used.
    virtual ~DisplayListOp() { CRASH(); }
    static void operator delete(void* ptr) { CRASH(); }
    /** static void* operator new(size_t size); PURPOSELY OMITTED **/
    static void* operator new(size_t size, LinearAllocator& allocator) {
        return allocator.alloc(size);
    }

实现:

LinearAllocator主要用于多个对象需要重复申请,同时这些对象的生命周期都类似的情况。
实现原理即需要使用该内存分配的对象,需要使用new placement的方式,不需要自己申请内存,申请内存统一使用LinearAllocator来申请。在LinearAllocator内部分配了主要通过页的方式来申请内存,每页4kb,每页之间通过单链表的方式来组织。
1. 当需要申请内存时,判断当前页是否满足需要内存大小的申请。
2. 如果满足,则直接返回当前内存,将指针游标指向下一个内存开始。
3. 如果不满足,则需要重新申请一页大小的内存,将内存除了Page结构大小外的地址开始返回。
4. 如果需要,也可以在每个申请的内存之间加入一定的标记,用于内存的管理。
#pragma once

class LinearAllocator
{
public:
	LinearAllocator();
	~LinearAllocator();

	void* alloc(size_t size);

private:
	class Page;

	Page* newPage(size_t size);

	Page* mHeadPage;
	Page* mCurrentPage;
	void* mNext;
	size_t mMemoryCount;
};
#include <stdio.h>
#include <stdlib.h>
#include "LinearAllocator.h"

class LinearAllocator::Page
{
public:
	Page()
	{
		mNextPage = NULL;
	}

	~Page()
	{
	}

	void* operator new(size_t size, void* buf)
	{
		return buf;
	}
	
	//this is the memory begin, add the page size is 4, so the next is the real memory
	void* start()
	{		
		return (void*)((size_t)this + sizeof(Page));
	}

	void* end(size_t size)
	{
		return (char*)start() + size;
	}

	Page* mNextPage;
};

//page size is 4kb
const int ONE_PAGE_SIZE = 4096;
#define ALIGN_INT(x) (x + sizeof(int) -1) &~(sizeof(int) -1)

LinearAllocator::LinearAllocator()
{
	mHeadPage = mCurrentPage = NULL;
	mNext = NULL;
	mMemoryCount = 0;
}

//delete all the memory
LinearAllocator::~LinearAllocator()
{
	Page* p = mHeadPage;
	while(p)
	{
		Page* pNext = p->mNextPage;
		p->~Page();
		free(p);
		p = pNext;
	}
}

LinearAllocator::Page* LinearAllocator::newPage(size_t size)
{
	size_t allocSize = ALIGN_INT(sizeof(Page)+ size);
	mMemoryCount += allocSize;
	void* p = malloc(allocSize);
	return new(p) Page();
}

void* LinearAllocator::alloc(size_t size)
{
	size = ALIGN_INT(size);

	if (NULL == mHeadPage)
	{
		mHeadPage = mCurrentPage = newPage(ONE_PAGE_SIZE);
		mNext = mCurrentPage->start();
	}
	else if ((char*)mNext + size > mCurrentPage->end(ONE_PAGE_SIZE))
	{
		Page* p = newPage(ONE_PAGE_SIZE);
		mCurrentPage->mNextPage = p;
		mCurrentPage = p;
		mNext = mCurrentPage->start();
	}

	void* ptr = mNext;
	mNext = (char*)mNext + size;
	return ptr;
}

使用方式:

class AllocTest
{
public:
	AllocTest()
	{
		mCount ++;
		a = mCount;
		b = a+1;
		c = b+1;
	}
	void* operator new (size_t size, LinearAllocator& linearAlloc)
	{
		return linearAlloc.alloc(size);
	}

	void dump()
	{
		cout<<"a = "<<a<<"  b="<<b<<"  c="<<c<<endl;
	}

	int a;
	int b;
	int c;

	static int mCount;
};

int AllocTest::mCount = 0;

class LinearAllocTest
{
public:
	LinearAllocTest()
	{
		AllocTest* test1 = new(mLinearAlloc)AllocTest();
		AllocTest* test2 = new(mLinearAlloc)AllocTest();
		AllocTest* test3 = new(mLinearAlloc)AllocTest();
		AllocTest* test4 = new(mLinearAlloc)AllocTest();

		test1->dump();
		test2->dump
	}

	~LinearAllocTest()
	{

	}

private:
	LinearAllocator mLinearAlloc;
};

同时也可以参考Android源码:
system/core/include/utils/LinearAllocator.h

你可能感兴趣的:(android,内存分配,HWUI)