我如何重载 new/stl 以使未知对象更快?

Posted

技术标签:

【中文标题】我如何重载 new/stl 以使未知对象更快?【英文标题】:How do i overload new/stl to make unknown objects faster? 【发布时间】:2011-04-07 03:13:26 【问题描述】:

在我的问题profiling: deque is 23% of my runtime 中,我的问题是“新”占我运行时间的很大一部分。问题是

我必须在许多不同的类/结构上大量使用 new 关键字(我有超过 200 个,并且是设计使然)。我使用了很多 stl 对象、迭代器和字符串。我使用 strdup 和其他分配(或免费)函数。

我有一个函数被调用超过 200 万次。它所做的只是创建 stl 迭代器,它占用了超过 20% 的时间(但据我所知,stl 被优化得非常好,调试使它变慢了)。

但请记住,我需要分配和释放这些迭代器 >2m 次以及其他经常调用的函数。如何优化 new 和 malloc 关键字/函数?特别是对于我没有写的所有这些类/结构和类/结构(stl 和其他)

虽然分析表明 i(和 stl?)使用 new 关键字比其他任何东西都多。

【问题讨论】:

你使用的是什么编译器版本? “做某事最快的方法就是不做”。为什么要分配200万件物品?可以避免其中一些吗?如果您对一种类型的对象有一些特定的瓶颈,那么池分配器可能会有所帮助。尝试编写一个比编译器提供的更快的通用分配器是非常乐观的。 【参考方案1】:

寻找避免分配/释放的机会,方法是添加您自己的管理层以回收已分配的内存和对象,或修改它们的分配器。有很多关于 STL 分配器的文章:

http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4079 http://bmagic.sourceforge.net/memalloc.html http://www.codeproject.com/KB/stl/blockallocator.aspx

我已经看到大型多映射代码只需替换默认分配器即可从无法使用的缓慢变为非常快。

【讨论】:

Boost 具有符合标准的池分配器,可以直接插入 STL 容器:boost.org/doc/libs/release/libs/pool/doc/interfaces/… +1, new 在 STL 中仅表示它委托给用户指定的分配器。不过,我有一个程序,其中分配器的结果与零的检查实际上产生了可衡量的影响!【参考方案2】:

你不能让malloc 更快。你也许可以让new 更快,但我敢打赌你可以找到不给他们打电话的方法。

找到对任何东西的过多调用的一种方法是仔细阅读代码以查找它们,但这很慢且容易出错,而且它们并不总是可见的。

找到它们的简单且万无一失的方法是pause the program a few times and look at the stack。 请注意,您实际上并不需要测量任何东西。如果某件事发生需要花费大量时间,这就是您在每次暂停时看到它的概率,目标是找到它。 您确实得到了粗略的测量结果,但这只是发现问题的副产品。

Here's an example 这是在一系列阶段中完成的,从而导致很大的加速因子。

【讨论】:

其实我正在解析一个生成的文本文件。我需要新的每把钥匙在那里。它的 8mb 文本......我认为有超过 100 万个键,更不用说值了。有很多电话。然而事实证明,我只调用了 malloc 3 次(它是一个库,而不是我自己的代码),而我的新代码是 >1Mill 以及几乎是一个 malloc 的 strdup。我通过一次分配一大块并删除了簿记来加快速度(因为除非我删除所有内容,否则我不需要删除任何内容)-编辑-我这样做的速度提高了 20% 以上。但是我的 strdup 不返回 char* 而是我自己的高效字符串 obj @acidzombie24:我只是在猜测,因为我不知道您要做什么,但是每条信息在获得和需要之间都有生命周期,而且只有在这些时间之间需要存储。文件是如何生成的?您需要存储密钥多长时间?听起来大分配很聪明。是什么让你的字符串 obj 更有效率?这些是我会遇到的设计问题,但随机暂停可以确定地定位问题,因此您不会优化不需要的东西。 其实我也做了随机暂停。它进入了我使用的重型库,新的和 strdup。现在它只进入那个库。嗯...我的字符串 obj 是 struct MyStringint len; char sz[0]; 并确保将 ptr 对齐到 4 字节(我可以将 len 更改为 2,但 4 很好)我不会进入生命周期,但在应用程序关闭之前将对象保留在内存中是可以接受的,因为它每次只运行几秒钟。我的字符串也从未修改过,我检查比较的长度。我可能会丢弃它并 cmp 4 个字节的 sz。如果它的 2 个字母,则永远不应该考虑第 4 个字节的问题 @acidzombie24: 1) 什么库,它进入库的样本占了很大的百分比,但从哪里来?堆栈上的每一行都可以节省时间。 2)那么数据去哪儿了?即如果直接进入数据库,也许你可以边做边做,并使用固定数组,从而减少所有新的。 3) 如果您在字符串比较中没有看到 >1 个堆栈样本停止,则说明它没有花费足够的时间来进行优化。如果您确实看到它 > 一次,strcmp 会在第一个不相等的字节处停止,因此如果您需要加快速度,您可以只比较第一个字节,而不是长度。 其实strcmp代码还没有。我需要先编写几个单元测试来解析。真的,我只是发表评论说 malloc 可以更快。就像为该作业分配

以上是关于我如何重载 new/stl 以使未知对象更快?的主要内容,如果未能解决你的问题,请参考以下文章

为啥会出现分段错误/如何重载运算符?

如何用数组重载 ostream 运算符<<?

Java:更快的重载或 if/else

Java——重载和重写

通过 C++ 中的重载构造函数初始化未知类型的变量

运算符重载