2012-01-11 11 views
7

私はこのコンストラクトがパフォーマンスクリティカルセクションの一部である高性能コードについて取り組んでいます。char []からの安全でない文字列の作成

  1. stringが「スキャン」され、メタデータを効率的に格納されている:

    これは、いくつかのセクションに何が起こるかです。

  2. このメタデータに基づいて、メインストリングのチャンクはchar[][]に分かれています。
  3. char[][]string[]に転送する必要があります。

new string(char[])を呼び出すことができますが、結果をコピーする必要があることがわかりました。

この余分なコピーを避けるには、文字列の内部バッファーに直接書き込むことが可能でなければならないと思います。これは安全でない操作でも(オーバーフロー、フォワード互換性のような意味合いが多いことがわかります)。

私はこれを達成するいくつかの方法を見てきましたが、私は本当に満足していません。

どのようにこれを達成するための真の提案を持っていますか?

追加情報:
実際のプロセスは、必ずしも、それは実質的に「マルチストリング」操作ですchar[]への変換は含まれません。 3つのインデックスとその長さが追加されています。

StringBuilderは、少数のコンカットに対してオーバーヘッドが多すぎます。

はEDIT:原因、それはまさに私が求めているということであるもののいくつかのあいまいな側面に
は、私はそれを定式てみましょう。

これは何が起こるかです:

  1. 主な文字列がインデックス化されます。
  2. メイン文字列の一部がchar[]にコピーされます。
  3. char[]stringに変換されます。
  4. 私は何をしたいのですが、その結果、ステップ2と3をマージです

  1. 主な文字列がインデックス化されています。
  2. メインの文字列の一部がstringにコピーされます(そして、GCはfixedキーワードを適切に使用することによって処理中に手を離すことができます)。

そしてノートこれは外部のライブラリであり、そしてプロジェクトがそれに(後方互換性)に依存するので、私、[]文字列から出力タイプを変更することはできませんということです。

+2

この後、実際に文字列とは何をする必要がありますか?つまり、 'string []'への写像方法を見つけようとするのではなく、 'char []'として取り込み、 'int、int'の位置と長さのペアを格納することができます必要なときにいつでも部分配列を引き出すために元の配列を参照する必要があります。 –

+0

ここでは、どのコードを改善しようとしているのか分かりません。 –

+2

文字列クラスは特別です。それは定義上不変であり、コピーを伴う。これを回避しようとすると、GCや他のマネージコード(文字列がプールされている)に問題があるかどうかを尋ねています。 – Nikki9696

答えて

2

は:

string s = GetBuffer(); 
fixed (char* pch = s) { 
    pch[0] = 'R'; 
    pch[1] = 'e'; 
    pch[2] = 's'; 
    pch[3] = 'u'; 
    pch[4] = 'l'; 
    pch[5] = 't'; 
} 

私は(少なくとも.NETはそれの一部を管理)世界は終わりが来るだろうと思うが、それは、StringBuilderが何をするかに非常に近いです。

StringBuilderが目的のために十分に速くないことを示すプロファイラデータがありますか、それとも前提ですか?

+0

仮定は、何度もコンカットさえなく、ほとんどの場合、2〜4コンカットしかないからです。我々は巨大な数について話しているわけではない。あなたが提供したコードサンプルをテストしましょう:)。 – Aidiakapi

+0

私はこれを今プロファイリングして、このメソッドでは2720、それには 'char []'と 'new string(theArray)'で4291、そして最後に 'StringBuilder'で5165を得ました。 – Aidiakapi

+0

これに副作用があるかどうか知っていますか? – Aidiakapi

2

あなたがしたいのは、小さな文字列の文字配列を再割り当てせずに、既存の文字列を複数の小さな文字列に '刻む'ことだと思います。これは管理対象の世界では機能しません。

なぜガベージコレクタが来て、compactionの間に元の文字列を収集したり移動したときに何が起こるかを考えてみましょう。その中の他の文字列はすべて、あなたがそれらを彫刻した元の弦。

編集:Benの回答(これは賢明ですが、IMHOは少し怖い)とは対照的に、StringBuilderをあらかじめ定義された容量で割り当てることができます。これにより、内部的なアレイ。 http://msdn.microsoft.com/en-us/library/h1h0a5sy.aspxを参照してください。

+0

私は応答が遅いことを知っています。しかし、私はサブストリングをメインストリングの一部としてマップしようとしていません。コピーしたいのですが、 'char []'にコピーしてから 'string'にコピーするのではなく、文字列に変換する。 – Aidiakapi

+0

CLRでこれを行う方法がわかりません。すべてのStringコンストラクタは、文字列配列(http://msdn.microsoft.com/en-us/library/6y4za026.aspx)へのポインタを取る安全でないものであっても、配列をコピーすることによって動作します。 –

+0

Ben Voigtはこれまでこれを行う方法の1つを既に提供していました。 – Aidiakapi

2

安全でないコードを使用して内部データ構造にマップするのではなく、独自のアドレッシングシステムを作成するだけです。小さな文字列の配列に(もchar[]として可読である)stringマッピング

アドレス情報(各部分のインデックス&長さ)のリストを構築すると違いはありません。したがってstring[]の代わりに新しいList<Tuple<int,int>>を作成し、そのデータを元の変更されていないデータ構造から正しい文字列を返すために使用してください。これは容易にstring[]のものにカプセル化することができます。あなたはどうなり

+0

依存関係のために戻り値の型を変更できないことを明確にしないと申し訳ありません。 – Aidiakapi

+0

この関数は絶対に 'string'だけを受け入れ、' string [] 'の実際のインスタンスのみを返さなければなりません(例えば' IList 'を返すことはできません)?ライブラリの場合は、より一般的なリターンタイプを好むでしょう。 –

+0

'Array'は' IList 'よりも具体的です。消費者が' IList 'として使用したいのであれば自由ですが、消費者がそれを使用していると仮定することはできませんArray.Copyでコードが壊れてしまいます。 (そして、彼らはCount to Lengthなどのリファクタリングをしなければならないでしょう) – Aidiakapi

0

.NETでは、別の文字列とデータを共有するStringのインスタンスを作成する方法はありません。それがなぜエリック・リッペルトのthis commentに現れるかについてのいくつかの議論。

+0

彼はデータを共有しようとしているのではなく、不可能ではないと言います。私は一度コピーしようとしています。 – Aidiakapi

+0

'String.Substring()'を探していますか? –

+0

いいえ。<、 "" string1 "のように.Substring(x1、y1)+" string2 ".Substring(x2、y2)+" string3 ".Substring(x3、y3)' – Aidiakapi

関連する問題