diff --git a/include/tc/core/solver.hpp b/include/tc/core/solver.hpp index 736792e..a04791f 100644 --- a/include/tc/core/solver.hpp +++ b/include/tc/core/solver.hpp @@ -42,7 +42,7 @@ namespace tc { namespace { struct Row { int gnr; - std::shared_ptr lst; + int *lst; }; struct Table { @@ -56,13 +56,46 @@ namespace { } }; + template + class BlockAllocator { + /// 4096 seems to be the best (on my machine anway) from profiling. + private: + int block = 0; + int next = 0; + std::vector data = {build()}; + + T *build() { + T *blk = new T[BlockSize]; + std::fill_n(blk, BlockSize, 0); + return blk; + } + + public: + T *operator()() { + if (next >= BlockSize) { + data.push_back(build()); + block++; + next = 0; + } + + return &data[block][next++]; + } + + ~BlockAllocator() { + for (auto &blk: data) { + delete[] blk; + } + } + }; + template class Tables { public: static constexpr unsigned int Rels = Rank * (Rank + 1) / 2 - Rank; private: - std::shared_ptr null_lst_ptr = std::make_shared(); + int *null_lst_ptr = new int; + BlockAllocator alloc; std::array, Rels> tables; std::array>, Rank> deps; @@ -94,7 +127,7 @@ namespace { if (row.lst == nullptr) { if (cosets.get(target, rel.gens[0]) != target and cosets.get(target, rel.gens[1]) != target) { - row.lst = std::make_shared(); + row.lst = alloc(); row.gnr = 0; } else { row.lst = null_lst_ptr; @@ -104,6 +137,10 @@ namespace { } } + ~Tables() { + delete null_lst_ptr; + } + void learn(int coset, int gen, int target, const tc::Cosets &cosets, std::priority_queue &facts) { if (target == coset) { for (auto &table: deps[gen]) {