3

SSCLIクレームの一部の C++ コードに埋め込まれたコメントは、String.Chars プロパティの管理されていない内部実装を参照しています。

この方法は実際には使用されません。JIT は文字列クラスのインデクサー メソッドのコードを生成します。

それで...これは何の魔法のコードですか?ジッターの要点は、さまざまな状況でさまざまなコードが生成されることだと理解しています。しかし、少なくとも最新の x64 Windows 7+ プラットフォームの場合、ジッターはどのようにこれを達成するのでしょうか? それとも本当に秘伝のタレ?

追加の詳細

少し前に、C# で文字列内の個々の文字を反復処理する最速の方法を探していました。安全でないコードに頼ったり、内容を ( 経由で) 複製したりすることのない最速の方法は、実際にはString.Chars プロパティToCharArray()の呼び出しである組み込みの文字列インデクサーであることが判明しました。最初の質問で、インデクサーが実際にどのように機能するかについて洞察を持っている人がいるかどうかを尋ねましたが、Skeet と Lippert の両方からの衝突にもかかわらず、私はそれについて何の回答も得られませんでした。だから私はそれを自分で掘り下げることにしました:

停止 1: mscorlib

mscorlib.dll を ildasm で調べると、これ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

MethodImplOptions 列挙型のドキュメントに記載されているように、「内部呼び出しは、共通言語ランタイム自体に実装されているメソッドへの呼び出しです。」2004 年の MSDN マガジンの記事SO の投稿の両方で、共有ソース CLIinternalcall内の ecall.cpp で、管理されていない実装への名前のマッピングを見つけることができることが示されています。

停止 2: ecapp.cpp

ecall.cpp のオンライン コピーを検索すると、次のようget_Charsに実装されていることがわかりCOMString::GetCharAtます。

FCIntrinsic("get_Chars", COMString::GetCharAt, CORINFO_INTRINSIC_StringGetChar)

停止 3: comstring.cpp

comstring.cppには実際に、1219 行目から GetCharAt の実装が含まれています。ただし、前に次のコメントがあります。

/*==================================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.
**
==============================================================================*/
4

1 に答える 1

1

まず、重要な点については Hans Passant のコメントを参照してください。

初期の .NET (CLR 1 および 2) では、CLR はStringおよびStringBuilder型をかなり特別にサポートしていました。実際、この 2 つのタイプは非常に緊密に連携していたためStringBuilder.ToString、実際の文字はどこにもコピーされず、文字列インデクサーは特別なジッター サポートを使用して、同じメモリ位置から文字をフェッチしていました。String.Charsスタック経由でインデックス整数を渡さないようにするために、元々のジッター サポートが必要だったのだと思いますが、その後、ジッターは改善されたようです。

.NET 4 にはStringBuilder (ropes ) の別の実装が付属しており、これはもはや のString処理方法に関連付けられていません。(コピー中にコピーする必要ToStringがありますが、追加ははるかに高速です。)これらの変更後、

  • StringBuilderインデクサーは、大きな文字列で はO(log n)まで劇的に遅くなります。ここ を参照してください。短い文字列であっても、インライン化されることはありません。
  • Stringインデクサーはまだ (未公開の) 特別なジッター サポートを使用しています。これは基本的に、シフト、加算、メモリ フェッチにインライン化されるか、最も近いループが許容するさらに高速なものになると思います。
于 2012-07-17T08:58:37.080 に答える