在更好的系统上更差的多线程性能(可能是由于 Deedle)
Worse multithreaded performance on better system (possibly due to Deedle)
我们正在使用 Deedle 处理多线程 C# 服务。四核当前系统与八核目标系统的测试表明,该服务在目标系统上的速度大约慢两倍,而不是快两倍。即使将线程数限制为两个,目标系统仍然慢了近 40%。
分析显示Deedle(/F#)中有大量的等待,使得目标系统基本上运行在两个核心上。非 Deedle 测试程序在目标系统上显示正常行为和卓越的内存带宽。
关于什么可能导致这种情况或如何最好地处理这种情况有什么想法吗?
编辑:似乎大部分时间都在调用 Invoke 时等待。
问题原来是使用 Windows 7、.NET 4.5(或实际上是 4.0 运行时)和在 F#/Deedle 中大量使用尾递归的组合。
使用 Visual Studio 的 Concurrency Visualizer,我已经发现大部分时间都花在等待 Invoke 调用上。仔细检查后,这些结果导致以下调用跟踪:
ntdll.dll:RtlEnterCriticalSection
ntdll.dll:RtlpLookupDynamicFunctionEntry
ntdll.dll:RtlLookupFunctionEntry
clr.dll:JIT_TailCall
<some Deedle/F# thing>.Invoke
搜索这些函数得到了多篇文章和论坛帖子,表明使用 F# 会导致对 JIT_TailCall 的大量调用,并且 .NET 4.6 有一个新的 JIT 编译器,它似乎可以处理一些相关问题对这些电话。虽然我没有发现任何提及与 locking/synchronisation 相关的问题,但这确实让我想到更新到 .NET 4.6 可能是一个解决方案。
然而,在我自己的 Windows 8.1 系统上,也使用 .NET 4.5,问题没有发生。在搜索了一些类似的 Invoke 调用之后,我发现该系统上的调用跟踪如下所示:
ntdll.dll:RtlAcquireSRWLockShared
ntdll.dll:RtlpLookupDynamicFunctionEntry
ntdll.dll:RtlLookupFunctionEntry
clr.dll:JIT_TailCall
<some Deedle/F# thing>.Invoke
显然,在 Windows 8(.1) 中,锁定机制已更改为不那么严格的内容,从而减少了等待锁定的需要。
因此,只有目标系统结合了 Windows 7 的严格锁定和 .NET 4.5 的低效 JIT 编译器,F# 大量使用尾递归才会导致问题。更新到 .NET 4.6 后,问题消失了,我们的服务符合预期 运行。
我们正在使用 Deedle 处理多线程 C# 服务。四核当前系统与八核目标系统的测试表明,该服务在目标系统上的速度大约慢两倍,而不是快两倍。即使将线程数限制为两个,目标系统仍然慢了近 40%。
分析显示Deedle(/F#)中有大量的等待,使得目标系统基本上运行在两个核心上。非 Deedle 测试程序在目标系统上显示正常行为和卓越的内存带宽。
关于什么可能导致这种情况或如何最好地处理这种情况有什么想法吗?
编辑:似乎大部分时间都在调用 Invoke 时等待。
问题原来是使用 Windows 7、.NET 4.5(或实际上是 4.0 运行时)和在 F#/Deedle 中大量使用尾递归的组合。
使用 Visual Studio 的 Concurrency Visualizer,我已经发现大部分时间都花在等待 Invoke 调用上。仔细检查后,这些结果导致以下调用跟踪:
ntdll.dll:RtlEnterCriticalSection
ntdll.dll:RtlpLookupDynamicFunctionEntry
ntdll.dll:RtlLookupFunctionEntry
clr.dll:JIT_TailCall
<some Deedle/F# thing>.Invoke
搜索这些函数得到了多篇文章和论坛帖子,表明使用 F# 会导致对 JIT_TailCall 的大量调用,并且 .NET 4.6 有一个新的 JIT 编译器,它似乎可以处理一些相关问题对这些电话。虽然我没有发现任何提及与 locking/synchronisation 相关的问题,但这确实让我想到更新到 .NET 4.6 可能是一个解决方案。
然而,在我自己的 Windows 8.1 系统上,也使用 .NET 4.5,问题没有发生。在搜索了一些类似的 Invoke 调用之后,我发现该系统上的调用跟踪如下所示:
ntdll.dll:RtlAcquireSRWLockShared
ntdll.dll:RtlpLookupDynamicFunctionEntry
ntdll.dll:RtlLookupFunctionEntry
clr.dll:JIT_TailCall
<some Deedle/F# thing>.Invoke
显然,在 Windows 8(.1) 中,锁定机制已更改为不那么严格的内容,从而减少了等待锁定的需要。
因此,只有目标系统结合了 Windows 7 的严格锁定和 .NET 4.5 的低效 JIT 编译器,F# 大量使用尾递归才会导致问题。更新到 .NET 4.6 后,问题消失了,我们的服务符合预期 运行。