[블로그를 쓸 틈이 없을 정도로 바쁘다] 표형 프로필 메모리 최적화 중 하나: 간단한 메모리 분배기

요즘은 생애 처음으로 코딩에 몰두해 블로그를 쓸 정력조차 없어졌다.이런 느낌은 그다지 좋지 않으니, 하루빨리 조절할 수 있기를 바란다.열심히 일한 후에 깊이 생각하는 것이 매우 중요하다고 생각한다. 
본론은 현재 국산 대형 게임 개발에서 엑셀 프로필을 자주 사용하고 있는데 이것은 텍스트 파일로 엑셀로 표를 편집한 후 txt 형식으로 저장하면 된다.일부 특수한 상황을 제외하고는 줄바꿈으로 분할된 csv 파일이라고 볼 수 있습니다.이런 프로필의 분석과 읽기는 어렵지 않으며, 인용부호, 줄 바꾸기 등 특수 기호에 대한 Excel의 방식을 똑똑히 시험하면 된다. 
이런 프로필은 공백 칸이 매우 많고 초대형 프로젝트에서 대량으로 중복된 문자열이 불쾌하다는 특징이 있다.그래서 이 파일을 메모리에 저장할 때 상당히 최적화될 여지가 있다.정력이 제한되어 있어서 나는 나의 결론을 직접 기록했다.
최적화는 크게 두 부분으로 나뉜다.
우선, 표를 불러올 때의 메모리 분배 최적화를 분석한다.상상할 수 있다. 대형 게임에는 표, 줄, 칸이 매우 많고 표를 메모리로 읽을 때 분배하는 횟수도 소털처럼 많다.좋은 점은 이 프로필들이 메모리에 읽히면 삭제할 필요가 없다는 것이다. 왜냐하면 게임 과정에서 언제든지 사용할 수 있기 때문이다.그래서 여기에 일부 메모리를 단독으로 방출할 수 없는 간이 메모리 분배기를 사용하는 것이 적합하다. 즉, 메모리를 반복적으로 신청하고 마지막으로 모두 방출하는 것이다. 
그 다음으로 문자열이 공유됩니다.표에 대량의 반복 짧은 문자열이 있는데, 인용 계수가 있는 문자열 라이브러리를 사용할 수 있다면, 메모리 최적화 공간이 있을 것이다.STL의 인용 계수 방식은 그다지 철저하지 않고 어느 정도 최적화되었을 뿐이다.그리고 오늘 방금 VS2010의 STL 라이브러리에서 인용 계수 기능을 제거한 것을 발견했습니다. 왜냐하면 다중 스레드의 버그일 수도 있다고 들었기 때문입니다. 
(공백 문자열이라면 메모리를 한 바이트밖에 차지하지 않았는데 이때 공유의 의미를 사용하면 크게 할인된다(오히려 int?)5~30바이트의 문자열에 최적화는 의미가 있다.) 
이 블로그에는 내가 방금 만든 메모리 분배기를 먼저 기록해라.인터페이스는 다음과 같이 간단합니다.
struct ROHeap;
typedef struct ROHeap ROHeap;

#ifdef __cplusplus      //  VS , cpp , extern "c", C++ 
extern "C" {
#endif

int ROHeapInit(ROHeap** heap, int page_size);
void* ROHeapAlloc(ROHeap* heap, int byte_size);
void ROHeapDeallocAll(ROHeap** heap);

#ifdef __cplusplus
}
#endif

구현: ROHeap.c
#include "ROHeap.h"
#include <malloc.h>
#include <assert.h>

typedef struct Page
{
	struct Page* next;
	char* p;
} Page;

#define SIZE_PAGE_HEAD ((int)(sizeof(Page)))

struct ROHeap
{
	Page* head;
	Page* cur_page;
	int page_size;
};

int ROHeapInit(ROHeap** heap, int page_size)
{
	ROHeap* h;
	assert( page_size==0 || page_size>SIZE_PAGE_HEAD );
	if ( page_size == 0 )
	{
		page_size = 4096;
	}
	else
	{
		page_size = page_size;
	}
	*heap = (ROHeap*)malloc( sizeof(ROHeap) );
	h = *heap;
	h->page_size = page_size;
	h->cur_page = (Page*)malloc( page_size );
	h->cur_page->next = 0;
	h->cur_page->p = (char*)h->cur_page + SIZE_PAGE_HEAD;
	h->head = h->cur_page;
	return 0;
}

void* ROHeapAlloc(ROHeap* heap, int byte_size)
{
	void* ret;
	assert( byte_size>0  && byte_size <= heap->page_size - SIZE_PAGE_HEAD );
	assert( heap->cur_page != 0 );

	if ( byte_size > heap->page_size - (heap->cur_page->p - (char*)heap->cur_page) )
	{
		heap->cur_page->next = (Page*)malloc( heap->page_size );
		heap->cur_page = heap->cur_page->next;
		heap->cur_page->next = 0;
		heap->cur_page->p = (char*)heap->cur_page + SIZE_PAGE_HEAD;
	}
	ret = heap->cur_page->p;
	heap->cur_page->p += byte_size;
	return ret;
}

void ROHeapDeallocAll(ROHeap** heap)
{
	Page* page;
	Page* next;
	assert(heap);
	page = (*heap)->head;
	do
	{
		next = page->next;
		free( page );
		page = next;
	}
	while ( page != 0 );
	free( *heap );
	*heap = 0;
}

간단한 설명:
1. 실현할 때 나는 순수한 C 언어를 사용했고 작성 과정에서 struct는 매우 불편하게 사용했다(typedefstruct의 작법은 여러 번 시험해 보았다).또한 C 언어의 국부 변수 성명은 반드시 함수가 시작되면 함수 중간에 놓으면 이상한 오류가 발생한다는 것을 주의해야 한다. error C2143: 문법 오류: 결핍 ";(유형 앞에)
2. VS2010은 파일 확장자가 c인지 cpp인지에 따라 컴파일 행위를 확정한다. cpp가 c 언어의 인터페이스를 호출할 때 extern'C'를 표시하고 매크로를 이용하여 보호하여 C 파일과 CPP 파일을 컴파일할 때 호환할 수 있도록 해야 한다(상례 참조).그 밑바닥 원리는 C++ 함수 이름 수식과 관련이 있으며, 구체적으로 관련 서적을 보십시오. 
3, VS 자체 메모리 누출 검사 도구 사용 방법: 우선 다음 세 개의 매크로를 순서대로 쓰십시오.
 #define CRTDBG_MAP_ALLOC
#include #include
그리고 검출이 필요한 곳에서 이 함수를 호출합니다:_CrtDumpMemoryLeaks(); 
Debug 모드에서 테스트하는 것이 좋습니다. Release 버전은 malloc를 다시 불러오지 않기 때문에 무효입니다.메모리 분배기를 쓸 때는 반드시 이것으로 잘 테스트해야 한다.

좋은 웹페이지 즐겨찾기