2009-05-04 14 views
2

私のPCにはデュアルコアCPUが搭載されています.2スレッドで処理を開始すると.NETリフレクション時間を2倍に短縮できますか?私は次のことを意味している "処理" することでマルチスレッドを使用して.NETリフレクションを高速化する

これらのタイプを4.queryingこれらの型 を3.processingそれのうち、すべてのタイプ(.GetTypes()) を2.gettingアセンブリ を1.loadingなどの方法 ため

YESの場合 - 最高(性能面)戦略がどうなるか:1つのスレッド内のアセンブリのすべての2 concurentで、プロセスのメタ情報

  1. 負荷スレッド
  2. 負荷及びプロセス独自スレッド内の各アセンブリ

答えて

1

ロードおよび別々のスレッドで、各アセンブリの処理は高速です。しかし、ちょっとだけ速いです。たとえば、MethodInfosをキャッシュすることで、より良い精度を得ることができます。

私はこのような最適化の必要性については疑問に思います。

結果:

 
warm up single threaded Time Elapsed 465 ms 
multi threaded Time Elapsed 173 ms 
single threaded Time Elapsed 456 ms 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Reflection; 
using System.Diagnostics; 

namespace ConsoleApplication12 { 
    class Program { 


     static void TimeAction(string description, Action func) { 
      var watch = new Stopwatch(); 
      watch.Start(); 
      func(); 
      watch.Stop(); 
      Console.Write(description); 
      Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds); 
     } 

     static void Main(string[] args) { 

      var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 

      // warm up 
      TimeAction("warm up single threaded",() => 
      { 
       foreach (var assembly in assemblies) { 
        assembly.GetTypes().Select(type => type.GetMethods()).ToArray(); 
       } 

      }); 

      List<Thread> threads = new List<Thread>(); 

      TimeAction("multi threaded",() => { 
       foreach (var assembly in assemblies) { 
        Thread t = new Thread(new ThreadStart(() => 
         assembly.GetTypes().Select(type => type.GetMethods()).ToArray() 
         )); 
        t.Start(); 
        threads.Add(t); 
       } 

       foreach (var thread in threads) { 
        thread.Join(); 
       } 
      }); 

      TimeAction("single threaded",() => 
      { 
       foreach (var assembly in assemblies) { 
        assembly.GetTypes().Select(type => type.GetMethods()).ToArray(); 
       } 

      }); 

      Console.ReadKey(); 
     } 
    } 
} 
1

あなたは絶対に大規模なライブラリを扱っている場合を除き、反射負荷が私の経験では、ひどく遅いものではありません。それはあなたの時間の無駄になる可能性があります。

これにもかかわらず、ThreadPool.QueueUserWorkItemをチェックしてください。これは簡単です。

foreach (Assembly a in "folder/something") { 
    ThreadPool.QueueUserWorkItem((object assem) => { 
     // do work 
    }, a); 
} 
3

心に留めておくべき事柄がいくつかあります:

  • 新しいスレッドを起動するには高価なので、タスクが短い場合は、オーバーヘッドが法外かもしれ住んでいました。独自のスレッドを開始する代わりにスレッドプールを使用することで、スレッドプールはその能力を最大限に引き出してスレッドを確実に再利用します。しかし、短時間で多くのタスクを起動しても、現在のスレッドプールの実装では最良の結果が得られません。

  • 特定のタスクには、おそらく操作の中で最も高価な部分になるI/Oが含まれているためです。 I/Oを待つためにいくつかのスレッドをオフにすると、パフォーマンスが向上しないことがあります。あなたがそれを測定するまで、あなたは本当に分からない。

  • 共有リポジトリにデータを保存している場合や、ファイル/画面に出力している場合は、それを同期させる必要があります。これは明らかに並行性を低下させます。

関連する問題