Marshal.PtrToStringUni() 与 new String()?
假设我有一个 char* 类型的指向 unicode 字符串的指针,并且我知道长度:
char* _unmanagedStr;
int _unmanagedStrLength;
并且我有 2 种方法将其转换为 .NET 字符串:
Marshal.PtrToStringUni((IntPtr)_unmanagedStr, _unmanagedStrLength);
并且
new string(_unmanagedStr, 0, _unmanagedStrLength);
在我的测试中,两个调用给出了完全相同的结果,但是 new string()
比 Marshal.PtrToStringUni()
快 1.8 倍。
为什么会有这样的性能差异? 两者之间还有其他功能差异吗?
Suppose i have a pointer of type char* to unicode string, and i know the length:
char* _unmanagedStr;
int _unmanagedStrLength;
and i have 2 ways to convert it to .NET string:
Marshal.PtrToStringUni((IntPtr)_unmanagedStr, _unmanagedStrLength);
and
new string(_unmanagedStr, 0, _unmanagedStrLength);
In my tests, both calls gives me exactly the same result, but the new string()
is like 1.8x times faster than Marshal.PtrToStringUni()
.
Why is that performance difference?
Is there any another functional difference between the both?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从可用的源代码(Rotor)来看,System.String(Char*)构造函数通过CtorCharPtr()使用了经过高度优化的代码路径,它使用FastAllocateString()分配字符串。 Marshal.PtrToStringUni() 遵循完全不同的代码路径,它是用 C++ 编写的,看起来会复制字符串两次,而没有“快速分配器”的好处。
显然,不是同一个程序员在做这件事。几乎可以肯定,甚至不是同一个团队,因为代码适合不同的编程模型。最接近的共同点经理可能比他高四级。
不确定这会有什么帮助,请使用快速的。事故会在 Windows 上产生类似的异常。
Judging from available source code (Rotor), the System.String(Char*) constructor uses a heavily optimized code path through CtorCharPtr(), it allocates the string with FastAllocateString(). Marshal.PtrToStringUni() follows an entirely different code path, it is written in C++ and looks to be copying the string twice, without the benefit of a "fast allocator".
Clearly, not the same programmer worked on this. Almost certainly not even the same team since the code fits a different programming model. The closest manager in common was probably four levels up.
Not sure how that would be helpful, use the fast one. Mishaps would generate a similar kind of exception on Windows.
第二个不符合 CLS,需要不安全的代码,并且可能具有未确定的行为,这就是它可能更快的原因。还需要将指针固定非托管地址或垃圾收集器可能会重新分配它,这会导致代码更加混乱。除非您确定这是应用程序的瓶颈,否则您可能需要使用 PtrToStringUni 函数。
The second is not CLS compliant, requires unsafe code and might have undetermined behavior which is why probably it's faster. There's also a need to pin the pointer to the unmanaged address or the garbage collector might reallocate it which leades to a more cluttered code. Unless you've determined that this is a bottleneck for your application you'll probably want to use the PtrToStringUni function.