nfengine icon indicating copy to clipboard operation
nfengine copied to clipboard

Implement custom memory allocators

Open Witek902 opened this issue 10 years ago • 2 comments

Currently, all memory allocations are done via malloc/new. This is OK in some cases (unit tests), but using it for managing objects which are frequently created and deleted have flaws:

  • memory allocations are slow
  • it leads to virtual memory fragmentation
  • it's bad for CPU cache

TODO checklist:

  • [ ] Implement "main allocator" allowing to allocate arbitrary-sized memory blocks on heap or reserve memory pages directly (VirtualAlloc on Windows, mmap on Linux). The main allocator should be able to track memory usage and keep all allocations list in debug mode in order to trace for memory leaks (size, location, source file and line number of allocation request should be tracked) and bugs (e.g. double freeing a block).
  • [ ] Implement "suballocators":
    • [ ] memory pool allocator for objects of the same size (e.g. separate memory pools for entities, each component type, each resource type, etc. Each unique class size in general.) It should reserve a bigger block of memory and keep it allocated during the whole runtime. If there is a request for allocation a new object, but there is no free space in the block, another is reseved. Empty blocks should be released to keep memory usage as low as possible. ( https://www.google.pl/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0ahUKEwiot5Ceot_OAhUhKpoKHa83BuAQFgghMAE&url=https%3A%2F%2Fwww.thinkmind.org%2Fdownload.php%3Farticleid%3Dcomputation_tools_2012_1_10_80006&usg=AFQjCNEPMpqZp7L6D4yrE0AMQETpMyJjFQ&sig2=OQVco7umdbQ46Ipt0QVYxA&bvm=bv.131286987,bs.2,d.bGg&cad=rja )
    • [ ] Two-Level Segregate Fit allocator (http://www.gii.upv.es/tlsf/)
    • [ ] (FUTURE) single frame allocator - for things that are allocated only for one single frame
  • [ ] Replace all allocations based on malloc/new in nfCommon, nfCore and renderers. Ideally, each class should have overloaded new/delete operators to use memory pool allocator. This should be as simple to do as:
class Foo
{
    // creates memory pool allocator that allocates sizeof(Foo) blocks and
    // generates new/delete operators
    NFE_REGISTER_CLASS(Foo);
...
};
  • [ ] Implement custom STL allocator (http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement) and use in nfCommon, nfCore and renderers for std::string, std::vector, etc.

Write test cases and performance test of e.g. entities creation and deletion. Compare the performance after moving to the new allocators.

Witek902 avatar Dec 19 '14 14:12 Witek902

Last 2 points of the First Steps pique my interest - why stop using std::string, when we provide stl allocators? Is it because of all unused features, that the std::string gives over char arrays?

mkulagowski avatar Sep 08 '15 07:09 mkulagowski

@mkulagowski No, it's because performance. std::string uses memory allocation, which we should avoid. For example, at https://github.com/nfprojects/nfengine/blob/devel/nfEngine/nfCore/Mesh.cpp#L107 we could use simple C-string to concatenate the path (the string would be keeped on a stack). In unit tests we can use normal std::string, because we don't care performance much there.

Witek902 avatar Sep 08 '15 08:09 Witek902