3
\$\begingroup\$

I'm a bit confused on how to implement an allocator for my game engine. I'm currently trying to implement PhysX for the physics in my game and it requires an implementation of an abstract allocator class that they defined. I've only heard of allocators spoken about in a general and abstract way so I'm not sure about how they are precisely implemented.

Now what I'm not so certain is that should a game engine contain multiple different allocators for different aspects of the engine i.e a separate allocator for shaders, textures, physics engine, meshes, etc... and if so, how do you know what asset requires an allocator class for it?

Or do you have one allocator class that allocates memory for any type of object? and if so, how do you know how much memory you'd need for the runtime of your program?

In this gamasutra post: https://gamasutra.com/blogs/MichaelKissner/20151104/258271/Writing_a_Game_Engine_from_Scratch__Part_2_Memory.php

He chooses an arbitrary value of 64 objects to allocate memory for. If you have different types of objects, surely 1 type of object will take more memory than another type so why the arbitrary 64? I'm sure he was using 64 just as a replacement for N. But how do we define N here?

\$\endgroup\$
  • 1
    \$\begingroup\$ You may find this GDC talk on building a memory system useful. \$\endgroup\$ – DMGregory Apr 11 at 11:48
  • \$\begingroup\$ What kind, and how many, allocators you need depends on what you're doing with memory. If you want a particle system, then you should probably create a pool allocator, as it's often the most efficient for the job. If you have assets that are loaded and unloaded sporadically, you'll need a more dynamic allocator (which is often less performant). So it all depends on exactly how your game works. Many smaller games uses only heap allocation (new or malloc) and works fine. Custom memory allocation is an optimisation and dependent on your specific use-case (although, there are commonalities). \$\endgroup\$ – Ted Klein Bergman Apr 11 at 11:54
  • \$\begingroup\$ @TedKleinBergman Well currently just need to use it for PhysX as PhysX requires a memory allocator but it would be good to learn about this as I aspire to be an Engine Programmer. So what I'm getting is that I create allocators on a case by case basis for different resources? \$\endgroup\$ – Sammi3 Apr 11 at 11:57
  • 1
    \$\begingroup\$ Yes, basically. Although, many allocators works well in many different circumstances and can be reused. But remember that memory allocation is an optimisation, so you should often profile your use-case before implementing a more specific allocator. If you notice that your game is slow iterating through entities because they're scattered around in memory, you should probably change to an allocator that pack things tightly. But if you then notice that the overhead of packing the entities cost more performance, you should change to another allocator. It's a challenge of weighing pros and cons \$\endgroup\$ – Ted Klein Bergman Apr 11 at 12:05
  • 1
    \$\begingroup\$ They talk about it a little in the gamasutra link under Memory Manager Types in Games. Basically, you identify an issue and try to solve that issue. Their example is that when you render a scene, you use a lot of memory that are not needed in the next frame. Instead of constantly asking for memory and freeing memory each frame, you allocate a chunk of memory that you just reuse every scene. Very common. The basic rule is that calling the kernel/OS for memory (using new or malloc) is slow, so you should do this as little as possible. \$\endgroup\$ – Ted Klein Bergman Apr 11 at 12:12
4
\$\begingroup\$

What kind, and how many, allocators you need depends on what you're doing with memory. If you want a particle system, then you should probably create a pool allocator, as it's often the most efficient for the job. If you have assets that are loaded and unloaded sporadically, you'll need a more dynamic allocator (which is often less performant). So it all depends on exactly how your game works. Many smaller games uses only heap allocation (new or malloc) and works fine. Custom memory allocation is an optimisation and depends on your specific use-case (although, there are commonalities).

Although, many allocators works well in many different circumstances and can be reused. But remember that memory allocation is an optimisation, so you should often profile your use-case before implementing a more specific allocator. If you notice that your game is slow iterating through entities because they're scattered around in memory, you should probably change to an allocator that pack things tightly. But if you then notice that the overhead of packing the entities cost more performance, you should change to another allocator. It's a challenge of weighing pros, cons and restrictions.

They talk about it a little in the gamasutra link under Memory Manager Types in Games. Basically, you identify an issue and try to solve that issue. Their example is that when you render a scene, you use a lot of memory that are not needed in the next frame. Instead of constantly asking for memory and freeing memory each frame, you allocate a chunk of memory that you just reuse every scene. Very common. The basic rule is that calling the kernel/OS for memory (using new or malloc) is slow, so you should do this as little as possible.

Why they chose to use the arbitrary value of 64 is because you want to preallocate objects in order to avoid asking the kernel for more memory every time you need a new object. But the 64 is a bit too generic and should probably be changed depending on for what the allocator is used. But this requires some profiling or knowledge about your memory needs.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you. I think I was getting confused with all the new terminology I was coming across. This has cleared my mind up. Currently, I just need to implement an allocator for PhysX as I have no memory optimisations that I require for now. Thank you again ! \$\endgroup\$ – Sammi3 Apr 11 at 12:22
  • 1
    \$\begingroup\$ I haven't used PhysX, but I'd suggest then to keep it simple to begin with. Maybe even just a wrapper around malloc and free! Just to get you started. Then when you have everything up and running, you could try to profile and reason about the best allocator for your case. I often do my allocators before I have a use-case, which often causes bugs that are hard to find, or I'll have to rewrite the allocator because it didn't fit my program. \$\endgroup\$ – Ted Klein Bergman Apr 11 at 12:27
  • 1
    \$\begingroup\$ Oh, PhysX requires the user to implement an abstract class for allocating memory for it to use but they provide a sample of an implementation so I'll just copy that for now \$\endgroup\$ – Sammi3 Apr 11 at 12:30
  • \$\begingroup\$ Sounds reasonable. Good luck! \$\endgroup\$ – Ted Klein Bergman Apr 11 at 12:33
  • 1
    \$\begingroup\$ 64 is the kind of number you'd pick when creating an object pool. Rather than allocate individual objects you take them from a pool of free objects. Rather than deleting expired objects you return them to the free pool. If the free pool is empty you allocate some more to extend it, but how many more? You might have a good idea of this but you might not. You don't want to allocate too few or you'll be allocating too often. You don't want to allocate too many or you're wasting memory. So you pick a number (such as 64) and tune & test around it until you get a good balance. \$\endgroup\$ – Maximus Minimus Apr 11 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.