Written by: Wednesday, March 02, 2011
By now, we probably all know that the latency of the garbage collector on Xbox 360 and Windows Phone 7 can be a problem. One solution is to avoid frequent memory allocations by using resource pools (or free-lists).
This blog post provides some information about the resource pool implementation provided by the DigitalRune libraries.
The DigitalRune Helper library contains a general implementation of a resource pool: ResourcePool<T>. The projects DigitalRune Geometry and Physics make extensive use of this class. For example, the collision detection in DigitalRune Geometry creates and removes contacts every frame. The type that stores the contact information is reused using a resource pool to minimize the number of newly allocated objects.
Here is an example how to create a resource pool for an object of type ObjectXyz:
ResourcePool<ObjectXyz> Pool = new ResourcePool<ObjectXyz>( () => new ObjectXyz(), // Create the object. obj => obj.Initialize(), // Initialize the object. (Optional) obj => obj.Uninitialize()); // Uninitialize the object. (Optional)
The constructor of the ResourcePool<T> requires 3 parameters: A create callback, an initialize callback and an uninitialize callback. In the example above the callbacks are implemented using lambda expressions. The initialize and the uninitialize callbacks are optional. (The last two parameters can be null.)
Using this resource pool objects of the given type can be obtained when needed and recycled after use:
var obj = Pool.Obtain(); // Do something with the object.... // Return the object to the resource pool when no longer needed.Pool.Recycle(obj);obj = null;
Resource pools are initially empty. New objects are created on demand – so a resource pool never runs out of objects.
By consistently using the resource pool and the Obtain/Recycle pattern throughout the application unnecessary garbage can be avoided.
In some situations we temporarily need a collection of a certain type (e.g. a List<T>). It is not necessary to manually create a new resource pool for every type T. The static class ResourcePools<T> provides resource pools for common types of collections (Lists, Hashsets, Stacks).
Here is an example that shows how to obtain a List<float> from the global resource pool.
// Obtain an empty list from the global resource pool. List<float> list = ResourcePools<float>.Lists.Obtain(); // Do something with the list. ... // After use, recycle the list. (Note: It is not necessary to clear the list before // recycling. This is handled automatically.) ResourcePools<float>.Lists.Recycle(list);
The latest update of DigitalRune Geometry and Physics added support for multithreading. For example: By default, all collision checks in collision domain are computed in parallel. Most collision algorithms require temporary objects that are taken from internal resource pools. Therefore, it was crucial to make all resource pools thread-safe.
The implementation of ResourcePool<T> is thread-safe. Multiple threads can simultaneously obtain/recycle objects from the same resource pool.
Additionally, the current implementation is lock free – for the most parts. Locks can be expensive, we therefore tried to avoid locks whenever possible for optimal performance. (Internally, all threads have a local resource pool to prevent contention when multiple threads need to access the same resource. If one thread’s local pool is empty it tries to steal resources from another thread. But users don’t have to worry about these internals.)
The base class ResourcePool provides global control over all resource pools. For example,
Our implementation of a resource pool is not just intended for internal use by the DigitalRune libraries. We encourage you to use it in your own code. It is thoroughly tested and has proven useful in many situations. If you find it helpful, we’d like to hear your feedback.
But before you start adding resource pools for all game objects, never forget the 10 rules of performance:
“Measure, measure, measure, … (repeated 10 times)!” (Quote: Rico Mariani)
0 comment(s) so far...
A collection of the most useful blog articles can be found here:
Article Collection (on Documentation page)
DigitalRune is a trademark of Garstenauer Information Technology OG.
Garstenauer Information Technology OG Weingartenstrasse 35, 4452 Ternberg Austria (EUROPE) office@digitalrune.com