在一个应用程序中,我详尽地生成了许多子问题,并使用“std::set”操作来解决它们。为此,我需要在排序列表上“insert”和“find”元素以及“迭代”。
问题在于,对于数百万个子问题中的每一个,每次我在集合中插入一个元素时,“std::set”实现都会分配新的内存,这使得整个应用程序非常慢:
{ // allocate a non-value node
_Nodeptr _Pnode = this->_Getal().allocate(1); // <- bottleneck of the program
是否有一些 STL 结构允许我在“O(log(n))”中进行上述操作而不重新分配任何内存?
最佳答案
使用自定义分配器似乎可以减少构建和发布 std::set<...> 所花费的时间。 .下面是一个简单分配器的完整演示以及一个分析结果时间的程序。
#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 for 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) {
// this could try to 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;
for (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 from 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 from 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
关于c++ - 没有内存重新分配的 std::set 的替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24096466/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
通过rubykoans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John
我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re