FrameAllocator

From TDN

Contents


Introduction

The FrameAllocator class in Torque is something that not a lot of people know about unless they get an assert about increasing the frame size. This is a shame, because the FrameAllocator is one of the most useful classes for any application, and Torque is no exception.

What Does it Do?

One of the major slowdowns in functions is dynamic memory allocation. Constantly querying the OS or (in the case of Torque) the memory manager for free pages is often unneeded since all you really want to do is allocate, say, a temporary buffer for a string or something. Consider the following code:

for( int i = 0; i < someBigNumber; i++ )
{
   char *foo = new char[someDynamicLen];
   ...
   delete [] foo;
}

Common occurance in code, right? However in Torque there is a better way. Enter the FrameAllocator. The FrameAllocator is initialized in "game/main.cpp" with the code:

FrameAllocator::init(3 << 20);

This gives the frame allocator a 3 meg allocation size by default which you can use for your purposes. What purposes? Why to allocate a dynamic amount of memory without the overhead of a memory allocation.

Learning by Example

The best way to get this idea straightened out is to see it in action, so lets re-write that previous loop:

for( int i = 0; i < someBigNumber; i++ )
{
   U32 prevWaterMark = FrameAllocator::getWaterMark();
   char *foo = (char *)FrameAllocator::alloc( sizeof( char ) * someDynamicLen );
   ...
   FrameAllocator::setWaterMark( prevWaterMark );
}

In this example it isn't necesasary to have the 'sizeof( char )' since the size of a char in bytes is 1, but it is important to note that 'FrameAllocator::alloc' takes an alloc size in bytes. For example:

F64 *foo = new F64[5];

Is *very* different from:

F64 *foo = (F64 *)FrameAllocator::alloc( 5 ); // THIS IS INCORRECT!

See what I mean now?

A Better Way

You must be saying, "This looks like a pain, what if I forget to reset the watermark or something?" Well you'd be screwed, but luckily there is a better way! It's called the FrameAllocatorMarker class. It will take care of the watermark stuff for you. So lets re-write that loop again!

for( int i = 0; i < someBigNumber; i++ )
{
   FrameAllocatorMarker fooAlloc;
   char *foo = (char *)fooAlloc.alloc( sizeof( char ) * someDynamicLen );
   ...
}

The FrameAllocatorMarker class stores the watermark for the FrameAllocator in its constructor. Then when it goes out of scope, it's destructor is called, and it will restore the watermark. Isn't that easy?!

Even Easier?

Yes, you can make this EVEN EASIER! However this class is targeted specifically at one task, which is the temporary array. It's called FrameTemp, and it's a templated class. It's constructor and destructor perform the same watermark management. Lets re-write the loop for the last time...

for( int i = 0; i < someBigNumber; i++ )
{
   FrameTemp<char> foo( someDynamicLen ); // NOTE!
   ...
}

It is important to note that the argument to the constructor is NOT the size in bytes, like the call to 'alloc' on the FrameAllocator or FrameAllocatorMarker.

FrameTemp<F64> foo(5);
F64 *bar = new F64[5];

Both give you the same amount of memory in this case.

--Pat Wilson 17:40, 17 Jun 2005 (CDT)