如何在 .net 中对 MemoryMappedFiles 使用 x64 互锁操作

Posted

技术标签:

【中文标题】如何在 .net 中对 MemoryMappedFiles 使用 x64 互锁操作【英文标题】:How to use x64 Interlocked Operations against MemoryMappedFiles in .net 【发布时间】:2014-09-23 10:27:41 【问题描述】:

我需要对 .NET 中 MemoryMappedFiles 中的内存使用互锁操作(CompareExchange、增量等)。

我发现这个answer 是一个非常相似的问题。问题是联锁操作不是从 64 位操作系统上的 kernel32(或任何其他)dll 导出的(参见例如http://blog.kalmbachnet.de/?postid=46)。

有没有其他方法可以在 64 位 .NET 进程的内存块上调用互锁函数?

【问题讨论】:

我会尝试使用调用互锁函数的导出函数编写自己的 C Dll,并从 .NET 中 PInvoke。 @AlexFarber 好点!我只是想问这个:) 你知道我是否可以很容易地找到编译器内在联锁函数的 ASM 实现(例如http://msdn.microsoft.com/en-us/library/2ddez55b(v=vs.80).aspx)?这样我就不必自己重新发明 ASM 代码了 您不需要这样做,只需从本机 Dll 中调用所需的函数,编译器将完成剩下的工作。我的意思是,对于您需要的每个互锁函数,编写调用互锁函数的导出 Dll 函数。 使用这种原子访问函数的目的是使其内联,因此开销绝对最小。一旦你必须 pinvoke,那么这一点就完全丢失了,避免一个命名的同步对象就没有意义了。 @HansPassant 在我的例子中,我共享一个包含数百个长值的内存缓冲区。为了避免争用,我需要数百个同步对象(互斥锁等)。我也希望 Interlocked 因为那些强制通过内存缓存行推动新值(而不是具有不特定时间的内存屏障) - 但你是对的,P/Invokes 可能会完全破坏这个好处:| 【参考方案1】:

自己编写一个小型 C++/CLI 帮助程序库,提供托管代码可以使用的互锁操作。

我相信最快的互操作路径是公开一个托管类,该类在内部调用一个非托管函数,该函数本身在互锁的内在函数上使用。这样,您甚至不必通过 PInvoke。

【讨论】:

不幸的是,这不是真的 - C++/CLI 比带有抑制检查的 P/Invoke 慢 - 参见例如这里:codeproject.com/Articles/253444/… 或这里:xinterop.com/index.php/2013/05/01/… 所以 P/Invoke 是要走的路(不幸的是,每次调用它仍然会发布十几个指令) 第一篇文章似乎表明 C++ 包装器更快。在第 2 篇文章中,C++ 包装器慢得多,以至于我开始怀疑。也许没有打开优化或执行了额外的工作(实际上 - C++ 包装器仅通过中间类调用 sqrt。为什么?)。在这两篇文章中,基准时间都非常小。很多噪音。 DateTime.Now 也不是很精确。通常,它以 15ms 的步长增加。他的测试在 10-30 毫秒范围内。我不相信任何一篇文章,也不会花时间进行更多调查。 我同意你的发现。要点是,如果您想要最大速度,您需要超越与托管本机转换相关的所有堆栈跟踪探测等。使用 P/Invokes,您可以通过指定 SuppressUnmanagedCodeSecurity 属性来执行此操作。使用 C++/CLI 包装器,默认情况下您会获得所有这些检查,据我所知,您无法快捷方式。

以上是关于如何在 .net 中对 MemoryMappedFiles 使用 x64 互锁操作的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .net 中对 HTTPS 请求进行数字签名?

如何在 .NET Core 中对 Spotify 进行经过身份验证的调用

如何让 mvc 管道在 .net core 5 中对 oidc 进行身份验证

如何在 ASP.NET MVC 视图中对数据进行分组?

如何在 .Net 中创建和解析标签、长度、值 (TLV) 并在 Base64 中对其进行编码

在 asp.net MVC 中对表进行排序