【发布时间】:2016-08-27 07:52:08
【问题描述】:
我正在研究 Windows 7 上的 c++ 应用程序的性能,该应用程序执行大量计算和大量小分配。基本上,我使用 Visual Studio 采样分析器观察到了一个瓶颈,它归结为文件的解析和类型的巨大树结构的创建
class TreeStruct : std::map<key, TreeStructPtr>
{
SomeMetadata p;
int* buff;
int buffsize;
}
- 在解析过程中创建了一万个这样的结构
- 缓冲区不大,1字节到几百字节
分析器报告最昂贵的功能是
- 免费(13000 个独家样品,38% 独家样品)
- 新运营商(13000 个独家样品,38% 独家样品)
- realloc(4000 个独家样本,13% 独家样本)
我设法优化并减少了对
的分配- 新运营商(2200 个独家样品,48% 独家样品)
- 免费(1770 个独家样品,38% 独家样品)
- 一些功能(73 个独占样本,1.5% 独占样本)
当我测量客户端等待时间(即客户端使用秒表等待操作处理)时,我的机器上的安装版本从 85 秒开始处理时间缩短到 16 秒的处理时间,这很棒。我继续在我们拥有的最强大的机器上进行测试,并且震惊地发现非优化版本只使用了3.5s,而优化了2s。相同的可执行文件,相同的操作系统...
问题:两台现代机器上怎么会出现这样的差异?
以下是规格: 85s到16s机器
3.5s 到 2s 机器
处理是单线程的。
【问题讨论】:
-
分配主要是操作系统的事情。除此之外,分配通常很昂贵。通常最好分配一次内存池并重用它们。小分配涉及内核内部相当多的内部管理开销。它也可能与分页和一般系统负载有关。
-
简·亨克是正确的。最好在需要它们之前一次分配所有结构,然后将它们保存在某种集合中。然后在需要时将它们从收藏中取出。当您不再需要它们时,将它们放回集合中并将它们标记为可用。
-
你在第二台机器上有更多的缓存和更快的内存。动态分配的内存量是多少?
-
“我正在研究一个 c++ 应用程序的性能 [...],它正在执行 [...] 很多小分配”最大的问题。尽管多年来 CRT 中的堆实现不断改进,但分配仍然带来相当大的开销。如果您避免进行大量小分配(这是 .NET 轻松胜过本机 C++ 程序一个数量级的领域),它通常会显着提高性能。看看 P/Invokes 到本机计算内核中的 .NET 实现是否可以提供更好的性能会很有趣。
-
基准测试不足永远是常见的原因。当您在启用调试堆的情况下运行慢速版本时,您会看到这样的差异。此外,应该缓慢的是读取文件。比分配内存慢很多很多倍。标准错误是重复运行程序,它不再从磁盘读取文件,而是从文件系统缓存中读取文件。最后但并非最不重要的是可用的页面文件空间量,这是分配内存的唯一实际成本。很大程度上取决于机器上运行的其他内容。
标签: c++ windows performance memory-management benchmarking