c++ - Alternative for std::set without memory reallocation? -


in application generate lot of subproblems exhaustively , solve them using "std::set" operations. need "insert" , "find" elements , "iterate" on sorted list.

the problem each of millions of subproblems "std::set" implementation allocates new memory each time insert element in set makes whole application slow:

{   // allocate non-value node     _nodeptr _pnode = this->_getal().allocate(1); // <- bottleneck of program 

is there stl-structure allows me to above operations in "o(log(n))" while not reallocating memory?

using custom allocator seems way reduce amount of time spent building , releasing std::set<...>. below complete demo of simple allocator program profiling resulting times.

#include <algorithm> #include <chrono> #include <cstdlib> #include <iostream> #include <iterator> #include <memory> #include <set> #include <vector>  // ----------------------------------------------------------------------------  template <typename t, std::size_t pool_size = 1024> class pool_allocator { private:     std::vector<t*> d_pools;     t*              d_next;     t*              d_end; public:     template <typename o>     struct rebind {         typedef pool_allocator<o, pool_size> other;     };     pool_allocator(): d_next(), d_end() {}     ~pool_allocator() {         std::for_each(this->d_pools.rbegin(), this->d_pools.rend(),                       [](t* memory){ operator delete(memory); });     }     typedef t value_type;     t*   allocate(std::size_t n) {         if (std::size_t(this->d_end - this->d_next) < n) {             if (pool_size < n) {                 // custom allocation bigger number of objects                 this->d_pools.push_back(static_cast<t*>(operator new(sizeof(t) * n)));                 return this->d_pools.back();             }             this->d_pools.push_back(static_cast<t*>(operator new(sizeof(t) * pool_size)));             this->d_next = this->d_pools.back();             this->d_end  = this->d_next + pool_size;         }         t* rc(this->d_next);         this->d_next += n;         return rc;     }     void deallocate(t*, std::size_t) {         // try recycle buffers     } };  // ----------------------------------------------------------------------------  template <typename allocator> void time(char const* name, std::vector<int> const& random) {     std::cout << "running " << name << std::flush;     using namespace std::chrono;     high_resolution_clock::time_point start(high_resolution_clock::now());      std::size_t size(0);     {         std::set<int, std::less<int>, allocator> values;         (int value: random) {             values.insert(value);         }         size = values.size();     }      high_resolution_clock::time_point end(high_resolution_clock::now());     std::cout << ": size=" << size << " time="               << duration_cast<milliseconds>(end - start).count() << "ms\n"; }  // ----------------------------------------------------------------------------  int main() {     std::cout << "preparing..." << std::flush;     std::size_t count(10000000);     std::vector<int> random;     random.reserve(count);     std::generate_n(std::back_inserter(random), count, [](){ return std::rand(); });     std::cout << "done\n";      time<std::allocator<int>>("default allocator      ", random);     time<pool_allocator<int, 32>>("custom allocator (32)  ", random);     time<pool_allocator<int, 256>>("custom allocator (256) ", random);     time<pool_allocator<int, 1024>>("custom allocator (1024)", random);     time<pool_allocator<int, 2048>>("custom allocator (2048)", random);     time<pool_allocator<int, 4096>>("custom allocator (4096)", random);     time<std::allocator<int>>("default allocator      ", random); }  // results clang/libc++: // preparing...done // running default allocator      : size=10000000 time=13927ms // running custom allocator (32)  : size=10000000 time=9260ms // running custom allocator (256) : size=10000000 time=9511ms // running custom allocator (1024): size=10000000 time=9172ms // running custom allocator (2048): size=10000000 time=9153ms // running custom allocator (4096): size=10000000 time=9599ms // running default allocator      : size=10000000 time=13730ms  // results gcc/libstdc++: // preparing...done // running default allocator      : size=10000000 time=15814ms // running custom allocator (32)  : size=10000000 time=10868ms // running custom allocator (256) : size=10000000 time=10229ms // running custom allocator (1024): size=10000000 time=10556ms // running custom allocator (2048): size=10000000 time=10392ms // running custom allocator (4096): size=10000000 time=10664ms // running default allocator      : size=10000000 time=17941ms 

Comments

Popular posts from this blog

database - VFP Grid + SQL server 2008 - grid not showing correctly -

jquery - Set jPicker field to empty value -

.htaccess - htaccess convert request to clean url and add slash at the end of the url -