comment buried in some C++ code声明中的SSCLI,指的是String.Chars属性的非托管内部实现:
实际上并未使用此方法。 JIT将为字符串类生成索引器方法的代码。
那么...... 是什么神奇的代码呢?我理解抖动的全部意义在于它们在不同情况下产生不同的代码。但至少,对于现代的x64 Windows 7+平台,/ a jitter如何实现这一目标呢?或者这是真正的秘密酱油?
其他详情
前段时间我正在寻找fastest way to iterate through individual characters in a string in C#。
事实证明,这是最快的方法,无需使用不安全的代码或复制内容(通过ToCharArray()
)
是内置的字符串索引器,它实际上是对String.Chars property的调用。就在我原来的
问题我问是否有人能够深入了解索引器的实际工作情况,但是尽管Skeet和
Lippert,我没有得到任何回应。所以我决定自己深入研究:
停止1:mscorlib
通过使用ildasm检查mscorlib.dll,我们可以看到String::get_Chars(int32 index)
只是一个internalcall
指针(加上一个属性):
.method public hidebysig specialname instance char
get_Chars(int32 index) cil managed internalcall
{
.custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 )
} // end of method String::get_Chars
如documentation for the MethodImplOptions enumeration中所述,“内部调用是对在公共语言运行时本身内实现的方法的调用。” 2004 MSDN Magazine article和SO post都表示internalcall
名称与非托管实现的映射可以在Shared Source CLI内的ecall.cpp中找到。
停止2:ecapp.cpp
搜索online copy of ecall.cpp表明get_Chars
已由COMString::GetCharAt
实施:
FCIntrinsic("get_Chars", COMString::GetCharAt, CORINFO_INTRINSIC_StringGetChar)
停止3:comstring.cpp
comstring.cpp确实包含GetCharAt的实现,从第1219行开始。除此之外,它之前是此注释:
/*==================================GETCHARAT===================================
**Returns the character at position index. Thows IndexOutOfRangeException as
**appropriate.
**This method is not actually used. JIT will generate code for indexer method on string class.
**
==============================================================================*/
答案 0 :(得分:1)
首先,请参阅Hans Passant对关键位的评论。
在早期的.NET(CLR 1和2)中,CLR对String
和StringBuilder
类型提供了相当多的特殊支持。事实上,这两种类型的工作非常紧密,StringBuilder.ToString
没有在任何地方复制实际字符,字符串索引器仍然使用特殊的抖动支持从相同的内存位置获取字符。我假设对String.Chars
的抖动支持最初是必要的,以避免通过堆栈传递索引整数,但从那时起抖动似乎有improved。
.NET 4带有StringBuilder
(ropes)的不同实现,不再与String
的处理方式相关联。 (它必须在ToString
期间复制,但附加速度要快得多。)经过这些更改后,
StringBuilder
索引器在大字符串上显着减慢到 O(log n)。 See here。它永远不会内联,甚至不会在短字符串中。String
索引器仍然使用(未发布)特殊抖动支持。我希望这个基本上可以转换为移位,添加和内存提取,或者更接近最近的循环允许的更快。