STL 替代方案

发布于 2024-07-05 16:08:20 字数 178 浏览 10 评论 0 原文

我真的很讨厌使用 STL 容器,因为它们使我的代码的调试版本运行得非常慢。 其他人使用什么来代替具有合理性能的调试构建 STL?

我是一名游戏程序员,这在我参与的许多项目中都是一个问题。 当你使用 STL 容器处理所有事情时,获得 60 fps 是相当困难的。

我的大部分工作都使用 MSVC。

I really hate using STL containers because they make the debug version of my code run really slowly. What do other people use instead of STL that has reasonable performance for debug builds?

I'm a game programmer and this has been a problem on many of the projects I've worked on. It's pretty hard to get 60 fps when you use STL container for everything.

I use MSVC for most of my work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

混吃等死 2024-07-12 16:08:20

EASTL 是一种可能性,但仍然不完美。 Electronic Arts 的 Paul Pedriana 对游戏应用程序中的各种 STL 实现的性能进行了调查,其摘要如下:
http://www.open-std.org /jtc1/sc22/wg21/docs/papers/2007/n2271.html

其中一些调整正在接受审查,以便纳入 C++ 标准中。

请注意,即使 EASTL 也不会针对非优化情况进行优化。 不久前我有一个 excel 文件,但我想我已经丢失了它,但对于访问来说,它是这样的:

       debug   release
STL      100        10
EASTL     10         3
array[i]   3         1

我最成功的就是滚动我自己的容器。 您可以将它们降低到接近 array[x] 的性能。

EASTL is a possibility, but still not perfect. Paul Pedriana of Electronic Arts did an investigation of various STL implementations with respect to performance in game applications the summary of which is found here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html

Some of these adjustments to are being reviewed for inclusion in the C++ standard.

And note, even EASTL doesn't optimize for the non-optimized case. I had an excel file w/ some timing a while back but I think I've lost it, but for access it was something like:

       debug   release
STL      100        10
EASTL     10         3
array[i]   3         1

The most success I've had was rolling my own containers. You can get those down to near array[x] performance.

壹場煙雨 2024-07-12 16:08:20

我的经验是,设计良好的 STL 代码在调试版本中运行缓慢,因为优化器已关闭。 STL 容器发出大量对构造函数和运算符= 的调用,这些调用(如果它们是轻量级的)会在发布版本中内联/删除。

此外,Visual C++ 2005 及更高版本在发布和调试版本中都启用了 STL 检查。 对于 STL 密集型软件来说,这是一个巨大的性能消耗。 可以通过为所有编译单元定义 _SECURE_SCL=0 来禁用它。 请注意,在不同的编译单元中具有不同的 _SECURE_SCL 状态几乎肯定会导致灾难。

您可以创建第三个构建配置并关闭检查,并使用它来进行性能调试。 我建议您保留调试配置并进行检查,因为它对于捕获错误的数组索引和类似的东西非常有帮助。

My experience is that well designed STL code runs slowly in debug builds because the optimizer is turned off. STL containers emit a lot of calls to constructors and operator= which (if they are light weight) gets inlined/removed in release builds.

Also, Visual C++ 2005 and up has checking enabled for STL in both release and debug builds. It is a huge performance hog for STL-heavy software. It can be disabled by defining _SECURE_SCL=0 for all your compilation units. Please note that having different _SECURE_SCL status in different compilation units will almost certainly lead to disaster.

You could create a third build configuration with checking turned off and use that to debug with performance. I recommend you to keep a debug configuration with checking on though, since it's very helpful to catch erroneous array indices and stuff like that.

小姐丶请自重 2024-07-12 16:08:20

我敢打赌你的 STL 使用经过检查的实现来进行调试。 这可能是一件好事,因为它会捕获迭代器溢出等。 如果这对你来说是一个很大的问题,可能有一个编译器开关可以将其关闭。 检查你的文档。

I'll bet your STL uses a checked implementation for debug. This is probably a good thing, as it will catch iterator overruns and such. If it's that much of a problem for you, there may be a compiler switch to turn it off. Check your docs.

云雾 2024-07-12 16:08:20

对于大型、性能关键的应用程序,专门针对您的需求构建自己的容器可能值得投入时间。

我在这里谈论的是真正的游戏开发。

For big, performance critical applications, building your own containers specifically tailored to your needs may be worth the time investment.

I´m talking about real game development here.

べ繥欢鉨o。 2024-07-12 16:08:20

如果您正在运行视觉工作室,您可能需要考虑以下事项:

#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0

这仅适用于迭代器,您要执行什么类型的 STL 操作? 您可能需要考虑优化内存操作; 即,使用 resize() 一次插入多个元素,而不是使用 pop/push 一次插入一个元素。

If your running visual studios you may want to consider the following:

#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0

That's just for iterators, what type of STL operations are you preforming? You may want to look at optimizing your memory operations; ie, using resize() to insert several elements at once instead of using pop/push to insert elements one at a time.

骑趴 2024-07-12 16:08:20

MSVC 在调试版本中使用了检查迭代器的非常重量级的实现,其他人已经讨论过,所以我不会重复它(但从这里开始)

您可能感兴趣的另一件事是您的“调试版本”和“发布版本”可能涉及更改(至少)4 个松散相关的设置。

  1. 生成 .pdb 文件(cl /Zi 和链接 /DEBUG),该文件允许符号调试。 您可能需要将 /OPT:ref 添加到链接器选项中; 链接器在不创建 .pdb 文件时会删除未引用的函数,但在 /DEBUG 模式下,它会保留所有这些函数(因为调试符号引用它们),除非您显式添加它。
  2. 使用 C 运行时库的调试版本(可能是 MSVCR*D.dll,但这取决于您使用的运行时)。 这归结为 /MT 或 /MTd (或者其他东西,如果不使用 dll 运行时)
  3. 关闭编译器优化 (/Od)
  4. 设置预处理器 #defines DEBUG 或 NDEBUG

这些可以独立切换。 第一种方法虽然增加了大小,但对运行时性能没有任何影响。 第二个使得一些函数更加昂贵,但是对malloc和free影响巨大; 调试运行时版本会小心地“毒害”它们所接触的内存,以清除未初始化的数据错误。 我相信,通过 MSVCP* STL 实现,它还消除了通常完成的所有分配池,因此泄漏准确地显示您所认为的块,而不是它正在子分配的更大的内存块; 这意味着它会在速度慢得多的情况下对 malloc 进行更多调用。 第三; 好吧,那个人做了很多事情(这个问题对该主题有一些很好的讨论)。 不幸的是,如果您希望单步运行顺利,则需要它。 第四个以各种方式影响许多库,但最值得注意的是它编译或消除了断言()和朋友。

因此,您可能会考虑使用这些选择的一些较小组合来进行构建。 我大量使用了具有符号(/Zi 和链接 /DEBUG)和断言(/DDEBUG)的构建,但仍然进行了优化(/O1 或 /O2 或您使用的任何标志),但保留了堆栈帧指针清除回溯(/Oy-)并使用正常的运行时库(/MT)。 它的性能接近我的发布版本,并且是半可调试的(回溯很好,单步在源代码级别有点古怪;当然,汇编级别工作得很好)。 您可以拥有任意多种配置; 只需克隆您的版本并打开调试中看起来有用的任何部分即可。

MSVC uses a very heavyweight implementation of checked iterators in debug builds, which others have already discussed, so I won't repeat it (but start there)

One other thing that might be of interest to you is that your "debug build" and "release build" probably involves changing (at least) 4 settings which are only loosely related.

  1. Generating a .pdb file (cl /Zi and link /DEBUG), which allows symbolic debugging. You may want to add /OPT:ref to the linker options; the linker drops unreferenced functions when not making a .pdb file, but with /DEBUG mode it keeps them all (since the debug symbols reference them) unless you add this expicitly.
  2. Using a debug version of the C runtime library (probably MSVCR*D.dll, but it depends on what runtime you're using). This boils down to /MT or /MTd (or something else if not using the dll runtime)
  3. Turning off the compiler optimizations (/Od)
  4. setting the preprocessor #defines DEBUG or NDEBUG

These can be switched independently. The first costs nothing in runtime performance, though it adds size. The second makes a number of functions more expensive, but has a huge impact on malloc and free; the debug runtime versions are careful to "poison" the memory they touch with values to make uninitialized data bugs clear. I believe with the MSVCP* STL implementations it also eliminates all the allocation pooling that is usually done, so that leaks show exactly the block you'd think and not some larger chunk of memory that it's been sub-allocating; that means it makes more calls to malloc on top of them being much slower. The third; well, that one does lots of things (this question has some good discussion of the subject). Unfortunately, it's needed if you want single-stepping to work smoothly. The fourth affects lots of libraries in various ways, but most notable it compiles in or eliminates assert() and friends.

So you might consider making a build with some lesser combination of these selections. I make a lot of use of builds that use have symbols (/Zi and link /DEBUG) and asserts (/DDEBUG), but are still optimized (/O1 or /O2 or whatever flags you use) but with stack frame pointers kept for clear backtraces (/Oy-) and using the normal runtime library (/MT). This performs close to my release build and is semi-debuggable (backtraces are fine, single-stepping is a bit wacky at the source level; assembly level works fine of course). You can have however many configurations you want; just clone your release one and turn on whatever parts of the debugging seem useful.

差↓一点笑了 2024-07-12 16:08:20

查看EASTL

Check out EASTL.

︶ ̄淡然 2024-07-12 16:08:20

如果您使用的是 Visual C++,那么您应该看看这个:

http://channel9.msdn.com/shows/Going+Deep/STL-Iterator-Debugging-and-Secure-SCL/

以及该页面中的链接,其中涵盖MS/Dinkware STL 执行的所有调试模式检查的各种成本和选项。

如果您要问这样一个与平台相关的问题,最好也提及您的平台......

If you're using Visual C++, then you should have a look at this:

http://channel9.msdn.com/shows/Going+Deep/STL-Iterator-Debugging-and-Secure-SCL/

and the links from that page, which cover the various costs and options of all the debug-mode checking which the MS/Dinkware STL does.

If you're going to ask such a platform dependent question, it would be a good idea to mention your platform, too...

海拔太高太耀眼 2024-07-12 16:08:20

使用 C++ 中的面向对象设计模式检查数据结构和算法
布鲁诺·普莱斯
http://www.brpreiss.com/

Checkout Data Structures and Algorithms with Object-Oriented Design Patterns in C++
By Bruno Preiss
http://www.brpreiss.com/

別甾虛僞 2024-07-12 16:08:20

ACE 库怎么样? 它是一个用于并发通信软件的开源面向对象框架,但它也有一些容器类。

What about the ACE library? It's an open-source object-oriented framework for concurrent communication software, but it also has some container classes.

风和你 2024-07-12 16:08:20

抱歉,我无法发表评论,所以这里有一个答案:EASTL 现已在 github 上提供: https://github .com/paulhodge/EASTL

Sorry, I can't leave a comment, so here's an answer: EASTL is now available at github: https://github.com/paulhodge/EASTL

冷了相思 2024-07-12 16:08:20

Ultimate++ 有自己的一组容器 - 不确定您是否可以与库的其余部分分开使用它们: http:// www.ultimatepp.org/

Ultimate++ has its own set of containers - not sure if you can use them separatelly from the rest of the library: http://www.ultimatepp.org/

作死小能手 2024-07-12 16:08:20

Qt 使用不同的接口重新实现了大多数 C++ 标准库内容。 它看起来相当不错,但商业授权版本可能会很昂贵。

编辑:Qt 此后已在 LGPL 下发布,这通常使得可以在商业中使用它产品没有商业版本(仍然存在)。

Qt has reimplemented most c++ standard library stuff with different interfaces. It looks pretty good, but it can be expensive for the commercially licensed version.

Edit: Qt has since been released under LGPL, which usually makes it possible to use it in commercial product without bying the commercial version (which also still exists).

执手闯天涯 2024-07-12 16:08:20

还有 ETL https://www.etlcpp.com/。 该库特别针对时间关键(确定性)应用程序

从网页:

ETL并不是为了完全取代STL,而是补充
它。 其设计目标涵盖四个主要领域。

  • 创建一组容器,其大小或最大大小在编译时确定。 这些容器应该主要是
    与 STL 中提供的等效,具有兼容的 API。
  • 与 C++ 03 兼容,但尽可能多地实现 C++ 11 新增功能。
  • 具有确定性行为。
  • 添加标准库中不存在的其他有用组件。

嵌入式模板库专为降低资源占用而设计
嵌入式应用程序。 它定义了一组容器、算法和
实用程序,其中一些模拟 STL 的部分内容。 没有动态
内存分配。 该库不使用堆。 全部
容器(侵入式类型除外)具有固定容量,允许
所有内存分配都在编译时确定。 图书馆是
适用于任何支持 C++03 的编译器。

There is also the ETL https://www.etlcpp.com/. This library aims especially for time critical (deterministic) applications

From the webpage:

The ETL is not designed to completely replace the STL, but complement
it. Its design objective covers four main areas.

  • Create a set of containers where the size or maximum size is determined at compile time. These containers should be largely
    equivalent to those supplied in the STL, with a compatible API.
  • Be compatible with C++ 03 but implement as many of the C++ 11 additions as possible.
  • Have deterministic behaviour.
  • Add other useful components that are not present in the standard library.

The embedded template library has been designed for lower resource
embedded applications. It defines a set of containers, algorithms and
utilities, some of which emulate parts of the STL. There is no dynamic
memory allocation. The library makes no use of the heap. All of the
containers (apart from intrusive types) have a fixed capacity allowing
all memory allocation to be determined at compile time. The library is
intended for any compiler that supports C++03.

怂人 2024-07-12 16:08:20

STL 容器不应在调试或其他任何地方运行“非常慢”。 也许你误用了它们。 你在调试时不会遇到像 ElectricFence 或 Valgrind 这样的东西,是吗? 它们会减慢任何进行大量分配的操作。

所有容器都可以使用自定义分配器,有些人用它来提高性能 - 但我自己从来不需要使用它们。

STL containers should not run "really slowly" in debug or anywhere else. Perhaps you're misusing them. You're not running against something like ElectricFence or Valgrind in debug are you? They slow anything down that does lots of allocations.

All the containers can use custom allocators, which some people use to improve performance - but I've never needed to use them myself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文