Windows与Linux的内存分配/std::list构造函数性能比较

5
我正在将 C++ 代码从 Linux 移植到 Windows。在此过程中,我发现下面这行代码在 Windows 下的速度比 Linux 慢了约 10 倍(在完全相同的硬件上):
list<char*>* item = new list<char*>[160000]; 

在Windows上,需要大约10毫秒的时间,而在Linux上只需要约1毫秒。请注意,这是平均时间。在Windows上运行此行100次需要约1秒钟。
这种情况发生在win32和x64上,两个版本都是在Release中编译的,并且通过QueryPerformanceCounter(Windows)和gettimeofday(Linux)测量速度。
Linux编译器是gcc。Windows编译器是VS2010。
有任何想法为什么会发生这种情况吗?

3
我看到有一场火并升起了…无论如何,你应该使用循环或类似的方式来完成任务,这些数字可能不会太有意义,因为10毫秒很容易被其他事情打扰。至少要测量几秒钟的时间。但即便如此,我猜想在Windows上分配内存的默认方式也更慢。试着玩弄一下,让它更像你程序中使用的模式。 - PlasmaHH
10
@EdHeal:我们修好了时间机器,你现在可以回到1998年并在那里过上幸福的生活。 - Sedat Kapanoglu
5
这与操作系统无关。你似乎在说如果 Doron 关闭一些服务,那么“new”会更快。我觉得这是胡说八道! - David Heffernan
3
VC10 STL-list的构造函数在构造时会分配一个(空)节点。这可能会在“构造”情况下带来很大的性能障碍。另一方面,我不知道gcc STL在构造std::list时做了什么,也许它以速度换取大小,而VC则以大小换取速度。我/你需要查看gcc版本的构造函数链。这是否对您的应用程序产生了性能影响? - Christopher
3
在查看了我找到的libstdc++实现后,似乎根节点并没有从堆上分配。这意味着在gcc中构建列表比vc版本稍快。我没有查看除此之外的其他实现差异。也许这个实现还有其他缺点,所以dikumware的实现者选择了分配根节点的方式...但是这样做,分配160k次根节点似乎会拖慢你的基准测试。 - Christopher
显示剩余11条评论
2个回答

10

这可能更多是库实现的问题。在大多数情况下,我期望只有一个分配,而list的默认构造函数不会分配任何东西。所以你试图衡量的是list的默认构造函数的成本(它被执行了160000次)。

我说“试图测量”,因为任何如此小的测量都更多地测量时钟抖动和分辨率,而不是代码执行时间。你应该将它放在循环中,以便经常执行几秒钟的运行时间。当你这样做时,你需要采取预防措施来确保编译器不会优化掉任何东西。

在Linux下,你至少要使用clock()进行测量;从gettimeofday得到的墙钟时间非常依赖于同时发生的其他事件。(但是不要在Windows下使用clock(),因为Windows的实现是错误的。)


1
我同意,这是在衡量std::list构造函数的成本,而不是内存分配。此外,使用内存分配后跟*放置-new[]*可以轻松地将两者分开测量。 - Ben Voigt
事实证明,list<>构造函数是大部分时间消耗的地方。 - Doron Yaacoby

2
我认为这个指令在两个操作系统中都需要较少的时间(不管其他任何因素)。在这种情况下,它需要的时间非常短,以至于您可能实际上正在测量计时器的分辨率。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接