sco*_*ttm 6 c# performance pinvoke marshalling
我即将开始阅读大量的二进制文件,每个文件有1000个或更多记录.不断添加新文件,因此我正在编写Windows服务来监视目录并处理收到的新文件.这些文件是用c ++程序创建的.我在c#中重新创建了结构定义并且可以很好地读取数据,但是我担心我这样做会最终导致我的应用程序死机.
using (BinaryReader br = new BinaryReader(File.Open("myfile.bin", FileMode.Open)))
{
long pos = 0L;
long length = br.BaseStream.Length;
CPP_STRUCT_DEF record;
byte[] buffer = new byte[Marshal.SizeOf(typeof(CPP_STRUCT_DEF))];
GCHandle pin;
while (pos < length)
{
buffer = br.ReadBytes(buffer.Length);
pin = GCHandle.Alloc(buffer, GCHandleType.Pinned);
record = (CPP_STRUCT_DEF)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(CPP_STRUCT_DEF));
pin.Free();
pos += buffer.Length;
/* Do stuff with my record */
}
}
Run Code Online (Sandbox Code Playgroud)
我认为我不需要使用GCHandle,因为我实际上并没有与C++应用程序通信,所有内容都是通过托管代码完成的,但我不知道另一种方法.
使用Marshal.PtrToStructure相当慢.我在CodeProject上发现了以下文章,它比较(和基准测试)阅读二进制数据的不同方法非常有用:
对于您的特定应用,只有一件事会给您明确的答案:简介.
这里所说的是我在使用大型PInvoke解决方案时学到的经验教训.编组数据的最有效方法是编组可以闪现的字段.这意味着CLR可以简单地执行相当于memcpy的操作来在本机代码和托管代码之间移动数据.简单来说,从结构中获取所有非内联数组和字符串.如果它们存在于本机结构中,则使用IntPtr表示它们,并根据需要将值封送到托管代码中.
我没有描述使用Marshal.PtrToStructure与使用本机API取消引用值之间的区别.如果通过剖析将PtrToStructure显示为瓶颈,那么这可能是您应该投资的.
对于大型层次结构,按需编组,而不是一次将整个结构拉入托管代码.在处理大型树结构时,我遇到的问题最多.编组一个单独的节点非常快,如果它是快速的,并且性能明智,它只能在那一刻编组你需要的东西.
| 归档时间: |
|
| 查看次数: |
5390 次 |
| 最近记录: |