问题描述
除非您正在编写操作系统或嵌入式系统的一部分,否则有什么理由这样做吗?我可以想象,对于一些经常创建和销毁的特定类,重载内存管理功能或引入对象池可能会降低开销,但在全局范围内做这些事情吗?
Unless you're programming parts of an OS or an embedded system are there any reasons to do so? I can imagine that for some particular classes that are created and destroyed frequently overloading memory management functions or introducing a pool of objects might lower the overhead, but doing these things globally?
添加
我刚刚在重载的删除函数中发现了一个错误 - 内存并不总是被释放.那是在一个不太重要的内存应用程序中.此外,禁用这些重载只会降低约 0.5% 的性能.
Addition
I've just found a bug in an overloaded delete function - memory wasn't always freed. And that was in a not-so memory critical application. Also, disabling these overloads decreases performance by ~0.5% only.
推荐答案
出于多种原因,我们重载了我工作的全局 new 和 delete 运算符:
We overload the global new and delete operators where I work for many reasons:
- 池化所有小分配 -- 减少开销,减少碎片,可以提高小分配重应用的性能
- 构建具有已知生命周期的分配 -- 忽略所有释放直到这段时间结束,然后将它们一起释放(诚然,我们更多地使用本地运算符重载而不是全局运算符)
- 对齐调整--缓存线边界等
- alloc fill -- 帮助暴露未初始化变量的使用
- 免费填充 -- 帮助暴露以前删除的内存的使用情况
- 延迟免费 -- 提高免费填充的有效性,偶尔提高性能
- sentinels 或 fenceposts -- 帮助暴露缓冲区溢出、不足和偶尔出现的野指针
- 重定向分配 -- 考虑到 NUMA、特殊内存区域,甚至在内存中保持独立的系统(例如嵌入式脚本语言或 DSL)
- 垃圾收集或清理——同样对那些嵌入式脚本语言很有用
- 堆验证 -- 您可以每 N 次分配/释放检查堆数据结构,以确保一切正常
- 会计,包括泄漏跟踪和使用快照/统计(堆栈、分配期限等)
- pooling all small allocations -- decreases overhead, decreases fragmentation, can increase performance for small-alloc-heavy apps
- framing allocations with a known lifetime -- ignore all the frees until the very end of this period, then free all of them together (admittedly we do this more with local operator overloads than global)
- alignment adjustment -- to cacheline boundaries, etc
- alloc fill -- helping to expose usage of uninitialized variables
- free fill -- helping to expose usage of previously deleted memory
- delayed free -- increasing the effectiveness of free fill, occasionally increasing performance
- sentinels or fenceposts -- helping to expose buffer overruns, underruns, and the occasional wild pointer
- redirecting allocations -- to account for NUMA, special memory areas, or even to keep separate systems separate in memory (for e.g. embedded scripting languages or DSLs)
- garbage collection or cleanup -- again useful for those embedded scripting languages
- heap verification -- you can walk through the heap data structure every N allocs/frees to make sure everything looks ok
- accounting, including leak tracking and usage snapshots/statistics (stacks, allocation ages, etc)
新建/删除记帐的想法非常灵活和强大:例如,您可以在发生分配时记录活动线程的整个调用堆栈,并汇总有关的统计信息.如果您没有空间将堆栈信息保存在本地,无论出于何种原因,您都可以通过网络发送堆栈信息.您可以在此处收集的信息类型仅受您的想象力(当然还有性能)的限制.
The idea of new/delete accounting is really flexible and powerful: you can, for example, record the entire callstack for the active thread whenever an alloc occurs, and aggregate statistics about that. You could ship the stack info over the network if you don't have space to keep it locally for whatever reason. The types of info you can gather here are only limited by your imagination (and performance, of course).
我们使用全局重载是因为它可以方便地将许多常见的调试功能挂在那里,并根据我们从这些重载中收集的统计数据对整个应用进行全面改进.
We use global overloads because it's convenient to hang lots of common debugging functionality there, as well as make sweeping improvements across the entire app, based on the statistics we gather from those same overloads.
我们仍然为个别类型使用自定义分配器;在许多情况下,您可以通过为例如提供自定义分配器来获得加速或功能.STL 数据结构的单点使用远远超过您可以从全局重载中获得的一般加速.
We still do use custom allocators for individual types too; in many cases the speedup or capabilities you can get by providing custom allocators for e.g. a single point-of-use of an STL data structure far exceeds the general speedup you can get from the global overloads.
看看一些用于 C/C++ 的分配器和调试系统,你会很快想到这些和其他想法:
Take a look at some of the allocators and debugging systems that are out there for C/C++ and you'll rapidly come up with these and other ideas:
- valgrind
- 电栅栏
- dmalloc
- dlmalloc
- 应用程序验证程序
- Insure++
- BoundsChecker
- ...以及许多其他...(游戏开发行业是一个值得关注的好地方)
(一本古老但开创性的书是Writing Solid Code,其中讨论了许多您可能希望在 C 中提供自定义分配器的原因,其中大部分仍然非常相关.)
(One old but seminal book is Writing Solid Code, which discusses many of the reasons you might want to provide custom allocators in C, most of which are still very relevant.)
显然,如果您可以使用这些优秀工具中的任何一个,您会希望这样做,而不是使用自己的工具.
Obviously if you can use any of these fine tools you will want to do so rather than rolling your own.
在某些情况下,它更快、更容易、业务/法律麻烦更少、平台尚无可用内容,或者只是更具指导意义:深入研究并编写全局过载.
There are situations in which it is faster, easier, less of a business/legal hassle, nothing's available for your platform yet, or just more instructive: dig in and write a global overload.
这篇关于有什么理由让全局 new 和 delete 过载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!