2016-12-21 11 views
1

私は一連のファイルをループで書くプログラムがあります。ファイル名は、メソッドに渡されるオブジェクトのパラメータを使用して作成されます。文字列連結のスピードアップ

public string CreateFilename(MyObject obj) 
{ 
    return "sometext-" + obj.Name + ".txt"; 
} 

これを行うよりパフォーマンスな方法があります:

ANTSパフォーマンスプロファイラが、これは犬遅く、私は理由がわからないと言いますか?メソッドは何千回もヒットし、入力オブジェクトが私のコントロール外であり、定期的に変更されるので、この目的のための離散方法以外の良い方法はわかりません。

String.Concat("sometext-", obj.Name, ".txt") 

これを行うにはより高速な方法はありません。

+1

'String.Format()'関数を使ってベンチマークしてみましたが、少し速くなっています。しかし、tbh、連結のコストは非常に高くはない、私はこれが不必要な最適化だと思いますか? – Jite

+0

これは 'obj'ごとにどれくらい頻繁に呼び出されますか? –

+1

は 'StringBuilder'を使用します。明らかに 'StringBuilder'はそれを一度しか初期化するための何らかのプライベートフィールドでなければなりません。しかし、それをあなたが望むだけ使うことができます。 –

答えて

8

コンパイラは、1つの呼び出しにあなたの2 concatsを最適化します。

+0

正確に。参照元はhttps://referencesource.microsoft.com/#mscorlib/system/string.cs,e7f761c274d2036b –

+0

ありがとうございます。私はそれを恐れていた。 – joelc

2

代わりに、クラス自体の中でファイル名を計算すると、オブジェクトを変更するときのパフォーマンスの低下に代わって、はるかに高速に実行されます。ファイル名を計算することがボトルネックであった場合、私は非常に心配しています。ファイルへの書き込みは、その名前を使用するよりも遅くなります。

以下のコードサンプルを参照してください。 (LINQPad 5の)最適化を使用してベンチマークしたところ、Test2はTest1より約15倍速く実行されました。とりわけ、Test2は小さな文字列オブジェクトを常に生成/破棄しません。

void Main() 
{ 
    Test1(); 
    Test1(); 
    Test1(); 
    Test2(); 
    Test2(); 
    Test2(); 
} 

void Test1() 
{ 
    System.Diagnostics.Stopwatch sw = new Stopwatch(); 
    MyObject1 mo = new MyObject1 { Name = "MyName" }; 
    sw.Start(); 
    long x = 0; 
    for (int i = 0; i < 10000000; ++i) 
    { 

     x += CreateFileName(mo).Length; 
    } 
    Console.WriteLine(x); //Sanity Check, prevent clever compiler optimizations 
    sw.ElapsedMilliseconds.Dump("Test1"); 
} 

public string CreateFileName(MyObject1 obj) 
{ 
    return "sometext-" + obj.Name + ".txt"; 
} 

void Test2() 
{ 
    System.Diagnostics.Stopwatch sw = new Stopwatch(); 
    MyObject2 mo = new MyObject2 { Name = "MyName" }; 
    sw.Start(); 
    long x = 0; 
    for (int i = 0; i < 10000000; ++i) 
    { 
     x += mo.FileName.Length; 
    } 
    Console.WriteLine(x); //Sanity Check, prevent clever compiler optimizations 
    sw.ElapsedMilliseconds.Dump("Test2"); 
} 



public class MyObject1 
{ 
    public string Name; 
} 

public class MyObject2 
{ 
    public string FileName { get; private set;} 
    private string _name; 
    public string Name 
    { 
     get 
     { 
      return _name; 
     } 
     set 
     { 
      _name=value; 
      FileName = "sometext-" + _name + ".txt"; 
     } 
    } 
} 

Iはまた、CreateFileNameにメモ化を追加試験が、それはかろうじてTest1を超える性能を改善し、それはハッシュ検索のための追加のオーバーヘッドと同等のステップを実行するため、それはおそらく、Test2をを打つことができませんでした。