{"id":36893318,"url":"https://github.com/f18m/boost-intrusive-pool","last_synced_at":"2026-01-12T15:39:58.428Z","repository":{"id":47022744,"uuid":"172327737","full_name":"f18m/boost-intrusive-pool","owner":"f18m","description":"A C++ memory pool that is Boost-friendly and performance oriented (zero-malloc).","archived":false,"fork":false,"pushed_at":"2025-11-20T21:47:59.000Z","size":659,"stargazers_count":23,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-02T00:34:28.558Z","etag":null,"topics":["boost","cpp11","cpp14","intrusive","intrusive-ptr","malloc-free","memory","pool","pool-allocator"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/f18m.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-02-24T11:11:14.000Z","updated_at":"2025-11-20T21:47:39.000Z","dependencies_parsed_at":"2025-04-06T21:20:19.511Z","dependency_job_id":"4e3c0316-9f41-4324-bb8d-fd74cc757352","html_url":"https://github.com/f18m/boost-intrusive-pool","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/f18m/boost-intrusive-pool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f18m%2Fboost-intrusive-pool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f18m%2Fboost-intrusive-pool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f18m%2Fboost-intrusive-pool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f18m%2Fboost-intrusive-pool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/f18m","download_url":"https://codeload.github.com/f18m/boost-intrusive-pool/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/f18m%2Fboost-intrusive-pool/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28341197,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["boost","cpp11","cpp14","intrusive","intrusive-ptr","malloc-free","memory","pool","pool-allocator"],"created_at":"2026-01-12T15:39:58.344Z","updated_at":"2026-01-12T15:39:58.418Z","avatar_url":"https://github.com/f18m.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.com/f18m/boost-intrusive-pool.svg?branch=master)](https://travis-ci.com/f18m/boost-intrusive-pool)\n\n# Boost Intrusive Pool\nThis project provides a C++ memory pool that is Boost-friendly and performance oriented.\n\n## Features and Limitations\nThe `boost_intrusive_pool` provides the following features:\n - **smart pointers**: once \"allocated\" from the pool items whose reference count goes to zero return\n   automatically to the pool;\n - **zero-malloc**: after a resize of `N` items, no memory allocations are EVER done until `M\u003c=N` active\n   items are in use;\n - O(1) allocate;\n - O(1) destroy (pool return);\n - use of standard, well-defined smart pointers: `boost::intrusive_ptr\u003c\u003e`; see [Boost documentation](https://www.boost.org/doc/libs/1_69_0/libs/smart_ptr/doc/html/smart_ptr.html#intrusive_ptr)\n - polymorphic-friendly pool: if A derives from `boost_intrusive_pool_item`, and B derives from A, the\n   memory pool of B works just fine;\n - Header-only;\n - Provides two variants: the **infinite memory pool**, which automatically enlarges if the number of active items goes over \n   initial memory pool size, and the **bounded memory pool**, which just returns `NULL` if trying to allocate more active\n   items than the configured limit;\n - **Optional** construction via an initialization function: when items are allocated out of the pool via the \n   `boost_intrusive_pool::allocate_through_init()` API, the `init()` member function of the memory-pooled objects \n   is called; C++11 perfect forwarding allows to pass optional parameters to the `init()` routine;\n - **Optional** construction via custom function: when items are allocated out of the pool via the \n   `boost_intrusive_pool::allocate_through_function()` the provided custom function is called with the memory-pooled \n   object as argument;\n - **Optional** recycling via custom function: when the pool is constructed, a custom function `std::function` can be\n   specified; when items return to the pool it will be called with the item being recycled as parameter; this allows\n   to perform special cleanup like releasing handles, clearing data structures, etc;\n - **Optional** recycling via alternative function: when items return to the pool, the memory pool can be configured\n   to invoke the `destroy()` member function of the memory-pooled objects; this allows\n   to perform special cleanup like releasing handles, clearing data structures, etc;\n\nOf course there are tradeoffs in the design that bring in some limitations:\n - requires all C++ classes stored inside the memory pool to derive from a base class `boost_intrusive_pool_item`;\n - provides `boost::intrusive_ptr\u003c\u003e` instead of the more widely-used `std::shared_ptr\u003c\u003e`:\n   reason is that `std::shared_ptr\u003c\u003e` puts the reference count in a separate block that needs a separate allocation\n   and thus memory pools based on `std::shared_ptr\u003c\u003e` (like https://github.com/steinwurf/recycle) cannot be\n   zero-malloc due to the heap-allocated control block;\n - requires C++ classes stored inside the memory pool to have a default constructor: reason is that to ensure\n   the spatial locality of allocated items (for better cache / memory performances) we use the `new[]` operator \n   which does not allow to provide any parameter;\n - adds about 32 bytes of overhead to each C++ class to be stored inside the memory pool.\n\n\n# How to Install\n\nSince this project is header-only it does not need any specific installation, just grab the latest release and put the\n`boost_intrusive_pool.hpp` file in your include path.\n\n# Requirements\n\nThis templated memory pool requires a C++11 compliant compiler (it has been tested with GCC 7.x and 8.x).\nIt also requires Boost version 1.55 or higher.\n\n\n# A Short Tutorial\n\nThe source code in [tests/tutorial.cpp](tests/tutorial.cpp) provides a short tutorial about the following topics:\n - `std::shared_ptr\u003c\u003e`\n - `boost::intrusive_ptr\u003c\u003e`\n - `memorypool::boost_intrusive_pool\u003c\u003e` (this project)\n \nand shows that:\n\n - allocating an item through `std::shared_ptr\u003cT\u003e` results in the malloc of `sizeof(T)` plus about 16bytes\n   (the control block);\n - allocating an item through `boost::intrusive_ptr\u003cT\u003e` results in the malloc of `sizeof(T)`: the refcount\n   is not stored in any separate control block;\n - creation of a `memorypool::boost_intrusive_pool\u003c\u003e` results in several malloc operations, but then:\n - creation of an item `T` from a `memorypool::boost_intrusive_pool\u003cT\u003e` does not result in any malloc\n\n\n# Example: Using the Default Constructor\n\nIn this example we show how to use memory-pooled objects that are initialized through their default constructor:\n\n```\n#include \"boost_intrusive_pool.hpp\"\n\nvoid main()\n{\n\tmemorypool::boost_intrusive_pool\u003cDummyClass\u003e pool(4); // allocate pool of size 4\n\t   // this results in a big memory allocation; from now on instead it's a zero-malloc world:\n\t\n\t{\n\t    // allocate without ANY call at all (max performances):\n\t    boost::intrusive_ptr\u003cDummyClass\u003e hdummy = pool.allocate();\n\t\n\t    // of course copying pointers around does not trigger any memory allocation:\n\t    boost::intrusive_ptr\u003cDummyClass\u003e hdummy2 = hdummy;\n\t\n\t    // if we observed the pool now it would report: capacity=4, unused_count=3, inuse_count=1\n\t    \n\t    \n\t    // now instead allocate using the DummyClass default ctor:\n\t    boost::intrusive_ptr\u003cDummyClass\u003e hdummy3 = pool.allocate_through_init();\n\t    \n\t} // this time no memory free() will happen!\n\n\t// if we observed the pool now it would report: capacity=4, unused_count=4, inuse_count=0\n}\n\n```\n\n\n# Example: Using a non-Default Constructor\n\nIn this example we show how to use memory-pooled objects that are initialized through their NON default constructor:\n\n```\n#include \"boost_intrusive_pool.hpp\"\n\nvoid main()\n{\n\tmemorypool::boost_intrusive_pool\u003cDummyClass\u003e pool(4); // allocate pool of size 4\n\t   // this results in a big memory allocation; from now on instead it's a zero-malloc world:\n\t\n\t{\n\t    // now instead allocate using the DummyClass NON default ctor:\n\t    boost::intrusive_ptr\u003cDummyClass\u003e hdummy3 = pool.allocate_through_init(arg1, arg2, arg3);\n\t    \n\t} // this time no memory free() will happen!\n}\n```\n\n# Performance Results\n\nThe following tables show results of some very simple benchmarking obtained on a desktop machine:\n\n```\nIntel(R) Core(TM) i5-4570 CPU @ 3.20GHz, 4 cores\n16GB DDR3\nlibc-2.27 (Ubuntu 18.04)\n```\n\nThe memory pool implementation is compared against a \"no pool\" solution (the `plain_malloc` line), which simply allocates\nitems directly from the heap through `malloc`.\nFor both the `boost_intrusive_pool` and the `plain_malloc` a very lightweight processing is simulated on the allocated\nitems so that these performance results show the gain you obtain if:\n - you intend to create a memory pool of large items, expensive to allocate each time;\n - the processing for each item is lightweight.\n\nThe benchmarks are then repeated considering 3 different memory allocators:\n 1. [GNU libc](https://www.gnu.org/software/libc/) default malloc/free implementation\n 2. [Google perftools](https://github.com/gperftools/gperftools) also known as tcmalloc\n 3. [Jemalloc](http://jemalloc.net/)\n\nMoreover 2 different memory allocation/deallocation patterns are considered:\n 1. `Continuous allocations, bulk free at end`: all 100 thousands large objects are allocated sequentially, lightweight-processed\n    and then released back to the pool/heap.\n 2. `Mixed alloc/free pattern`: the items are returned to the pool/heap in a pseudo-random order, potentially generating memory fragmentation\n    in the `plain_malloc` implementation.\n    \nFinally for each combination of memory allocator and allocation pattern we measure the mean time it takes to allocate an item\n(or retrieve it from the memory pool!) against the \"memory pool enlarge step\" configuration value. Of course the enlarge step\nparameter will affect only the memory pool perfomances so that in theory the \"plain malloc\" time should remain constant\n(i.e. all green lines should be flat in all graphs below!). In practice small variations are expected also in the measured\ntimes for the \"plain malloc\".\n\nResults for the `Continuous allocations, bulk free at end` benchmark follow:\n\n\u003ctable cellpadding=\"5\" width=\"100%\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\n\n![](tests/results/pattern_1_gnulibc.png)\n\n\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\n\n![](tests/results/pattern_1_tcmalloc.png)\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\n\n![](tests/results/pattern_1_jemalloc.png)\n\n\n\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\n\nResults show that with glibc allocator (regular malloc/free implementation), the use of a memory\npool results in up to 44% improvement (from an average of 134ns to about 76ns).\nWhen Google's tcmalloc or jemalloc allocators are in use the improvement grows to 67% and 76% respectively.\n\nThis is important to show that even if your software is using an optimized allocator the memory pool\npattern will improve performances considerably.\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003c/tbody\u003e\n\u003c/table\u003e\n\nResults for the `Mixed alloc/free pattern` benchmark follow:\n\n\u003ctable cellpadding=\"5\" width=\"100%\"\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\n\n![](tests/results/pattern_2_gnulibc.png)\n\n\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\n\n![](tests/results/pattern_2_tcmalloc.png)\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\n\n![](tests/results/pattern_2_jemalloc.png)\n\n\n\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\n\nThese results show that with a pattern where malloc and free operations are scattered and \"randomized\" \na little bit, regular allocators cannot avoid memory fragmentation and less spatial locality compared\nto a memory pool implementation.\n \nIn particular improvements go from 40% (glibc) to 53% (jemalloc) and up to 73% (tcmalloc).\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003c/tbody\u003e\n\u003c/table\u003e\n\nOf course take all these performance results with care.\nActual performance gain may vary a lot depending on your rate of malloc/free operations, the pattern in which they happen,\nthe size of the pooled items, etc etc.\nYou can find the source code used to generate these benchmark results in the file [tests/performance_tests.cpp](tests/performance_tests.cpp).\n\n\n\n# About Thread Safety\n\nThe memory pool has no locking mechanism whatsoever and is not thread safe.\nThe reason is that this memory pool is performance oriented and locks are not that fast, specially if you have many\nthreads continuosly allocating and releasing items to the pool.\nIn such a scenario, the best from a performance point of view, is to simply create a memory pool for each thread.\n\n\n# Other Memory Pools\n\nThis memory pool implementation has been inspired by a few other C++ implementations out there like:\n\n- https://github.com/steinwurf/recycle\n- https://thinkingeek.com/2017/11/19/simple-memory-pool/\n- https://github.com/cdesjardins/QueuePtr\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ff18m%2Fboost-intrusive-pool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ff18m%2Fboost-intrusive-pool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ff18m%2Fboost-intrusive-pool/lists"}