我真的很讨厌使用STL容器,因为它们使我的代码的调试版本运行得非常慢。其他人使用什么代替具有合理性能的STL进行调试构建?
我是一名游戏程序员,这对我所参与的许多项目都是一个问题。当你使用STL容器时,很难获得60 fps。
我在大部分工作中使用MSVC。
答案 0 :(得分:25)
EASTL是一种可能性,但仍然不完美。 Electronic Arts的Paul Pedriana对游戏应用程序中的各种STL实现进行了调查,其摘要见下文: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html
正在审核其中一些调整以包含在C ++标准中。
请注意,即使是EASTL也没有针对非优化案例进行优化。我有一个excel文件w /一段时间了一段时间但我想我已经失去了它,但是对于访问它是这样的:
debug release
STL 100 10
EASTL 10 3
array[i] 3 1
我所取得的最大成功就是滚动自己的容器。你可以将它们降到接近数组[x]的性能。
答案 1 :(得分:21)
我的经验是,设计良好的STL代码在调试版本中运行缓慢,因为优化器已关闭。 STL容器向构造函数发出大量调用,operator =在发布版本中内联/删除(如果它们很轻的话)。
此外,Visual C ++ 2005及更高版本在发布和调试版本中都为STL启用了检查。对于STL重型软件来说,这是一个巨大的性能。可以通过为所有编译单元定义_SECURE_SCL = 0来禁用它。请注意,在不同的编译单元中具有不同的_SECURE_SCL状态几乎肯定会导致灾难。
您可以创建第三个构建配置,并关闭检查并使用它来调试性能。我建议你保持一个调试配置但是检查,因为它有助于捕获错误的数组索引和类似的东西。
答案 2 :(得分:10)
如果您正在运行的视觉工作室,您可能需要考虑以下事项:
#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0
这只适用于迭代器,你正在进行什么类型的STL操作?您可能希望了解优化内存操作;即,使用resize()一次插入多个元素,而不是使用pop / push一次插入一个元素。
答案 3 :(得分:7)
对于大型,性能关键型应用程序,根据您的需求构建自己的容器可能值得投入时间。
我在这里谈论真正的游戏开发。
答案 4 :(得分:4)
我敢打赌你的STL使用经过检查的实现进行调试。这可能是一件好事,因为它会捕获迭代器超支等。如果这对您来说是个大问题,可能会有一个编译器开关将其关闭。检查你的文档。
答案 5 :(得分:4)
如果您使用的是Visual C ++,那么您应该看一下:
http://channel9.msdn.com/shows/Going+Deep/STL-Iterator-Debugging-and-Secure-SCL/
以及该页面的链接,其中包含MS / Dinkware STL执行的所有调试模式检查的各种成本和选项。
如果您要问这样一个平台相关的问题,那么提及您的平台也是一个好主意......
答案 6 :(得分:3)
查看EASTL。
答案 7 :(得分:3)
您可能感兴趣的另一件事是您的“调试版本”和“版本构建”可能涉及更改(至少)4个与松散相关的设置。
这些可以独立切换。第一个在运行时性能上没有任何成本,尽管它增加了大小。第二个使得许多功能更加昂贵,但对malloc和free有很大的影响;调试运行时版本小心地“毒害”它们与值接触的内存,以使未初始化的数据错误清晰。我相信在MSVCP * STL实现中它还消除了通常所做的所有分配池,因此泄漏显示了你想到的块,而不是它所分配的大块内存;这意味着它会使更多对malloc的调用更慢。第三;好吧,那个人做了很多事情(this question对这个问题有一些很好的讨论)。不幸的是,如果你想要单步进行顺利工作,那就需要它。第四个以各种方式影响许多库,但最值得注意的是它编译或消除了assert()和朋友。
因此,您可以考虑使用这些选项中较少的组合进行构建。我大量使用带有符号(/ Zi和link / DEBUG)和断言(/ DDEBUG)的构建,但仍然进行了优化(/ O1或/ O2或您使用的任何标志)但是保留了堆栈帧指针清除回溯(/ Oy-)并使用正常的运行时库(/ MT)。这接近我的发布版本并且是半可调试的(回溯很好,单步执行在源级别有点古怪;当然,程序集级别工作正常)。您可以拥有许多您想要的配置;只需克隆你的第一个版本,然后打开调试的任何部分就好了。
答案 8 :(得分:3)
对不起,我不能发表评论,所以这里有一个答案:EASTL现在可以在github上找到:https://github.com/paulhodge/EASTL
答案 9 :(得分:1)
Ultimate ++有自己的容器集 - 不确定你是否可以独立于库的其余部分使用它们:http://www.ultimatepp.org/
答案 10 :(得分:1)
ACE library怎么样?它是一个面向对象通信软件的开源面向对象框架,但它也有一些容器类。
答案 11 :(得分:1)
使用C ++中的面向对象设计模式检出数据结构和算法 由Bruno Preiss撰写 http://www.brpreiss.com/
答案 12 :(得分:1)
答案 13 :(得分:0)
STL容器不应该在调试或其他任何地方“非常慢”地运行。也许你在滥用它们。你是不是在调试中运行像ElectricFence或Valgrind这样的东西?他们放慢了许多分配的速度。
所有容器都可以使用自定义分配器,有些人用它来提高性能 - 但我自己从不需要自己使用它们。
答案 14 :(得分:0)
还有ETL https://www.etlcpp.com/。该库特别针对时间关键型(确定性)应用程序
从网页上:
ETL并非旨在完全替代STL,而是补充 它。其设计目标涵盖四个主要领域。
- 创建一组容器,这些容器的大小或最大大小在编译时确定。这些容器应在很大程度上 等效于STL中提供的内容,并带有兼容的API。
- 与C ++ 03兼容,但要实现尽可能多的C ++ 11添加。
- 具有确定性的行为。
- 添加标准库中不存在的其他有用组件。
嵌入式模板库旨在降低资源消耗 嵌入式应用程序。它定义了一组容器,算法和 实用程序,其中一些模仿STL的一部分。没有动态 内存分配。该库不使用堆。全部 容器(除了侵入式)具有固定的容量 所有内存分配将在编译时确定。图书馆是 适用于所有支持C ++ 03的编译器。