Skip to main content
GameDev.net gamedev.net
🔒 Locked

Memory Allocation Timings

Started by MatrixCubed Aug 2, 2002 at 9:01 AM 0 replies 500+ views
Original Post
MatrixCubed
MatrixCubed
Hello all, I've been messing around with seeing how fast/slow different memory allocation and freeing routines are, based on different amounts of memory required in the allocation. I wrote a simple program that tests malloc, new, HeapAlloc, VirtualAlloc, LocalAlloc, and GlobalAlloc. In the best case (allocating less than 1kb of memory), malloc/GlobalAlloc/LocalAlloc were the clear winners. In the worst case (allocating 256mb of memory), malloc/new/LocalAlloc were the winners. At this point, I'm presuming that I missed out on something in the Win32-specific memory allocation functions, so if you'd like to test these yourself on your own system, I've included the source code below. I don't have much experience with the Win32 functions, so I put in what appeared to be the most useful option flags. Also, I should mention that the CTimer class is a floating-point timer class I wrote, which you can grab here.
          

#include <stdio.h>

#include <CTimer.h>

#include <malloc.h>

#include <conio.h>

#include <winbase.h>


#pragma comment(lib, "CTimer.lib")

///////////////////////////////////////////////////////////////////////////////


void AllocateVirtualAlloc(int iBytes)
{

	void* lpBuffer = VirtualAlloc(NULL, iBytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	VirtualFree(lpBuffer, iBytes, MEM_DECOMMIT);

}

///////////////////////////////////////////////////////////////////////////////


void AllocateLocalAlloc(int iBytes)
{

	HLOCAL h = LocalAlloc(0, iBytes);
	LocalFree(h);

}

///////////////////////////////////////////////////////////////////////////////


void AllocateGlobalAlloc(int iBytes)
{

	HGLOBAL h = GlobalAlloc(0, iBytes);
	GlobalFree(h);

}

///////////////////////////////////////////////////////////////////////////////


void AllocateHeapAlloc(int iBytes)
{

	HANDLE h = HeapCreate(0, iBytes, iBytes);
	void* lpBuffer = HeapAlloc(h, 0, iBytes);
	HeapFree(h, 0, lpBuffer);
	lpBuffer = 0;

}

///////////////////////////////////////////////////////////////////////////////


void AllocateMalloc(int iBytes)
{

	unsigned char* lpBuffer = (unsigned char *)malloc(iBytes);
	free(lpBuffer);

}

///////////////////////////////////////////////////////////////////////////////


void AllocateNew(int iBytes)
{

	unsigned char* lpBuffer = new unsigned char[iBytes];
	delete [] lpBuffer;

}

///////////////////////////////////////////////////////////////////////////////


void main(void)
{

	CTimer* lpTimer = new CTimer();
	unsigned int iBytes = 1;
	float fTime = 0.0f, fResult = 0.0f;

	printf("Bytes          Method         Time (ms)\n");

	// Try all timers

	while (iBytes < 0x1fffffff)
	{


		// New / delete

		fTime = lpTimer->GetTime();
		AllocateNew(iBytes);
		fResult = lpTimer->GetTime() - fTime;
		printf("%10d     new/delete     %3.3f\n", iBytes, fResult);

		// Malloc

		fTime = lpTimer->GetTime();
		AllocateMalloc(iBytes);
		fResult = lpTimer->GetTime() - fTime;
		printf("%10d     malloc         %3.3f\n", iBytes, fResult);

		// HeapAlloc

		fTime = lpTimer->GetTime();
		AllocateHeapAlloc(iBytes);
		fResult = lpTimer->GetTime() - fTime;
		printf("%10d     heapalloc      %3.3f\n", iBytes, fResult);

		// GlobalAlloc

		fTime = lpTimer->GetTime();
		AllocateGlobalAlloc(iBytes);
		fResult = lpTimer->GetTime() - fTime;
		printf("%10d     globalalloc    %3.3f\n", iBytes, fResult);

		// LocalAlloc

		fTime = lpTimer->GetTime();
		AllocateLocalAlloc(iBytes);
		fResult = lpTimer->GetTime() - fTime;
		printf("%10d     localalloc     %3.3f\n", iBytes, fResult);

		// VirtualAlloc

		fTime = lpTimer->GetTime();
		AllocateVirtualAlloc(iBytes);
		fResult = lpTimer->GetTime() - fTime;
		printf("%10d     virtualalloc   %3.3f\n", iBytes, fResult);

		// Increase the amount of bytes

		iBytes *= 2;


	}


	printf("\npress any key to exit...\n");
	while (!kbhit()) { Sleep(1); }



}

///////////////////////////////////////////////////////////////////////////////

  
MatrixCubed
http://MatrixCubed.cjb.net [edited by - MatrixCubed on August 2, 2002 10:07:46 AM]
developer
developer
Not sure if you had some particular question, but here are some additional thoughts....

When allocating small blocks using the C Runtime libraries, there''s something called the small block heap you might want to look at. See _set_sbh_threshold() in MSDN. This affects all ways you allocate memory using the C runtime, e.g. new/malloc/calloc. LocalAlloc/GlobalAlloc/VirtualAlloc are Win32 functions not affected by this. When writing your own code you should allocate (small) memory from the stack where possible, which obviously is much faster. When allocating on the stack you need to be careful so you don''t cause a stack overflow though.
Often you can re-use buffers rather than doing frequent reallocations. Allocating and freeing memory can be expensive and should be avoided if possible.

Depending on the memory manager there''s a risk your application run into heap congestion if you allocate and free frequently, especially if you have multiple processors (serialization of threads if the heap manager is stupid, meaning your application doesn''t get faster with more processors added). Some people use 3rd party memory managers (such as SmartHeap from Microquill) to resolve heap congestion problems for multi-processor systems. Good programming reduces the risk of heap-congestion.

A good MSDN article about heap memory is: Heap: Pleasures and Pains

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.