C++/C# 互操作中的内存映射和 P/Invoke 性能
Posted
技术标签:
【中文标题】C++/C# 互操作中的内存映射和 P/Invoke 性能【英文标题】:Memory mapping and P/Invoke performance in C++/C# interop 【发布时间】:2016-12-09 18:49:26 【问题描述】:不久前我开发了一些 dll,以便 P/Invoke 从 C++ dll 到 C# 的一些东西。但是,我在硬实时环境中工作,P/Invoke 被证明太慢而无法执行某些操作。
所以我发现内存映射是一种(据说)更快的 P/Invoke 替代方案,并且在我的测试期间,C++ 方面看起来并不太简陋:
#include "stdafx.h"
#define BUF_SIZE 256
TCHAR szName[] = TEXT("MyFileMappingObject");
char* pcTest = "Message from C++";
int _tmain()
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
BUF_SIZE,
szName);
if (hMapFile == NULL)
_tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError());
return 1;
pBuf = (LPTSTR)MapViewOfFile(
hMapFile,
FILE_MAP_ALL_ACCESS,
0,
0,
BUF_SIZE);
if (pBuf == NULL)
_tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError());
CloseHandle(hMapFile);
return 1;
CopyMemory((PVOID)pBuf, pcTest, (strlen(pcTest) * sizeof(char*)));
std::cin.get();
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
我从这里改编了代码:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx
这里是 C# 方面:
static void Main(string[] args)
MemoryMappedFile pagedMemoryMap = MemoryMappedFile.OpenExisting("MyFileMappingObject", MemoryMappedFileRights.FullControl);
using (MemoryMappedViewAccessor fileMap = pagedMemoryMap.CreateViewAccessor())
var array = new byte[256];
fileMap.ReadArray(0, array, 0, 16); //Take notice on this line
var text = Encoding.ASCII.GetString(array);
Console.WriteLine(text);
Console.ReadKey();
它按预期工作,但这里有一个问题:ReadArray 方法中字节数组长度的固定大小。我想我必须将实际应用程序中实际字符串的长度写入不同的共享,然后用它来读取字符串值,但这似乎太麻烦了。考虑到我在实际应用程序中从 C++ 中实际读取的是结构数组(大部分仅包含字符串),我是否会从内存映射中获得任何收益,性能方面?我没有任何用可能没有预期结果的替代方案来膨胀稳定代码(尽管速度很慢)的意图,那么这种方法有什么真正的好处吗?有更好的选择吗?
【问题讨论】:
C# 不适合硬实时环境。垃圾收集器会错过你的时间。事实上,Windows 不适合硬实时环境,因为分页和中断处理会错过您的时间。软实时/接近实时是另一回事。 当然,我们不打算采用 1:1 的比例。 C# 部分仅用于可视化,并且值会不断快速地更新,即使我们错过了更高级别的一些更新也没关系。然而,使用软实时仿真器运行一切都很好,但是一旦我们连接到真正的硬件,事情就会变得很糟糕 【参考方案1】:内存映射文件非常适合跨进程共享数据。它们对于在同一内存空间中的模块之间共享毫无意义。
只需以普通方式将您的数据结构定义为引用类类型,然后将其固定。现在 C++ 可以直接使用普通的指针访问来访问数据结构了。
计数字符串在固定数组中与在内存映射文件中一样有效,但您不需要任何内核调用来设置它们。
【讨论】:
我喜欢你关于固定对象的建议。我会在星期一尝试并报告结果 今天是星期一吗? @GregM 离星期一还有几个不喜欢的地方 :)以上是关于C++/C# 互操作中的内存映射和 P/Invoke 性能的主要内容,如果未能解决你的问题,请参考以下文章