天天看點

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