2011-01-03 7 views
5

私はMCTS試験70-536 Microsft .Net Framework Application Dev Foundationの練習問題を抱えています。問題の1つは、同じものを実行する汎用クラスとオブジェクトタイプの2つのクラスを作成することです;ループがそのクラスを使用し、何千回も反復したものです。そして、タイマーを使用して、両方のパフォーマンスに時間をかけてください。 C# generics questionに同じクエストを求めるが、未回答の投稿がありました。ジェネリックスとオブジェクトのパフォーマンス

私のコードでは、まずジェネリッククラスを実行すると、処理にロガーがかかります。オブジェクトクラスを最初に実行すると、処理に時間がかかります。全体のアイデアは、ジェネリックスがより速く実行されることを証明することでした。

私はしばらく時間を節約するために元のユーザーコードを使用しました。私は特にコードに何か間違っているとは思わなかったし、結果に困惑した。なぜそのような結果が得られたのかを説明できるのでしょうか?ここで

おかげで、

Risho

はコードです:

class Program 
{ 
    class Object_Sample 
    {    
     public Object_Sample() 
     { 
      Console.WriteLine("Object_Sample Class"); 
     } 

     public long getTicks() 
     { 
      return DateTime.Now.Ticks; 
     } 

     public void display(Object a) 
     { 
      Console.WriteLine("{0}", a); 
     } 
    } 

    class Generics_Samle<T> 
    {    
     public Generics_Samle() 
     { 
      Console.WriteLine("Generics_Sample Class"); 
     } 

     public long getTicks() 
     { 
      return DateTime.Now.Ticks; 
     } 

     public void display(T a) 
     { 
      Console.WriteLine("{0}", a); 
     } 
    } 

    static void Main(string[] args) 
    {    
     long ticks_initial, ticks_final, diff_generics, diff_object; 
     Object_Sample OS = new Object_Sample(); 
     Generics_Samle<int> GS = new Generics_Samle<int>(); 

     //Generic Sample 
     ticks_initial = 0; 
     ticks_final = 0; 
     ticks_initial = GS.getTicks(); 

     for (int i = 0; i < 50000; i++) 
     { 
      GS.display(i); 
     } 
     ticks_final = GS.getTicks(); 
     diff_generics = ticks_final - ticks_initial; 

     //Object Sample 
     ticks_initial = 0; 
     ticks_final = 0; 
     ticks_initial = OS.getTicks(); 

     for (int j = 0; j < 50000; j++) 
     { 
      OS.display(j); 
     } 

     ticks_final = OS.getTicks(); 
     diff_object = ticks_final - ticks_initial; 

     Console.WriteLine("\nPerformance of Generics {0}", diff_generics); 
     Console.WriteLine("Performance of Object {0}", diff_object); 

     Console.ReadKey(); 
    } 
} 
+3

あなたの質問に対する回答を受け入れる必要があります。 – SLaks

+1

'Stopwatch'クラスを使うべきです。 – SLaks

+1

その答えを受け入れるためにあなたの質問ごとに与えられた最良の答えの横にある中空のチェックをクリックする必要があります。 – SLaks

答えて

5

テストが間違っています。方法は次のとおりです。

public void display(T a) 
{ 
    Console.WriteLine("{0}", a); // Console.WriteLine(string format, params object[] args) <- boxing is performed here 
} 

public void display(Object a)// <- boxing is performed here 
{ 
    Console.WriteLine("{0}", a); 
} 

したがって、どちらの場合でもボクシングを使用しています。あなたの時限コードがConsole.WriteLine()が含ま

public void add(long a) 
{ 
    Total += a; 
} 

public void display(Object a)// <- boxing is performed here 
{ 
    Total += (long) a;// <- unboxing is performed here 
} 
+0

私はこのコードを書いていませんでしたが、私はその本の内容をテストしたかっただけです。あなたのコメントでは、 "公共の空白表示(オブジェクト)"ボクシングはここで実行されると述べています。それを説明できますか?私はここに何もカバーしていないんですか? – Risho

+0

'long'は値の型です。値の型をオブジェクトにキャストするときは、「ボクシング」と呼ばれます。つまり、値型は参照型である特別な 'box'で囲まれています。この時点で.Netはこの 'ボックス'のためのメモリを割り当てる必要があり、これはあまりにも高速な操作ではありません。オブジェクトを値型にキャストすると、それは 'unboxing'と呼ばれ、値は 'box'から変数にコピーされます。シグネチャ 'method(オブジェクトa)でメソッドを呼び出すとき、.Netはあなたの' long'を 'object'に暗黙的にキャストし、ボクシングのためにパフォーマンスギャップを生み出します。 –

+0

'display'メソッド呼び出しで 'オブジェクト'のボクシングが行われ、' Console.WriteLine'の 'generic'にあるため、 'display'メソッドで使用している入力引数のタイプは関係ありません。メソッドコール - それでも起こっている。 –

8

あなたはジッタが実行できるように、それをタイミング前に、両方のクラスに別々の時間を実行する必要があります。

+0

+1これは私にとってもジッタのように聞こえる。 –

+0

彼のプロフィールをチェックして、受け入れ可能な回答があるかどうか確認しましたか? –

+1

@Henk - 少なくとも13の質問の後では、* 1つの*答えが受け入れられると思います。しかし、やはり受容性は視線の目にある。 –

3

なぜでしょうか?両方のint型は、Console.WriteLineを(文字列、オブジェクト)

編集を使用するために箱詰めする必要があります:あなたはConsole.WriteLineを(A)を使用する場合のToString()自体はそれほどボクシング http://weblogs.asp.net/ngur/archive/2003/12/16/43856.aspx

を起こしていないようです。私が思うはずのConsole.WriteLine(Int32)を呼び出すでしょう(これを確認するにはリフレクターを調べる必要があります)

+0

テキストブックは、ジェネリックスが高速であることを示しました。 – Risho

+0

ボクシングとアンボクシングを防ぐなら、それらはもっと速くなりますが、ここではそうではありません。 – Kikaimaru

+0

私はこれを理解しようとしています:Console.WriteLinesがしない限り、私はここで変換しません。そうであれば、「ボクシング/アンボクシング」なしでどのように結果を表示しますか? – Risho

9

私が見ることができる最初の問題は、DateTimeオブジェクトを使って時間を測定していることですあなたのアプリケーションで(非常に短い間隔で)。

Stopwatchクラスを使用する必要があります。コードをベンチマークしようとすると精度が向上します。

2番目の問題は、JIT(Just-In-Timeコンパイル)を許可していないことです。あなたのコードへの最初の呼び出しは、単にJITされなければならないので、もっと長くかかるでしょう。その後、結果が得られます。

ループ中に何が起こっているのかを正確に把握できるように、タイミングを開始する前にコードを1回呼び出すだけです。

+1

+1 'Stopwatch'の場合 –

3
  1. :のようなより良いあなたのクラスならば、例えば、値の総和をカウントすることになります。それは時間の99.999999%を占めるでしょう。
  2. この状況でジェネリックがより速くなるという仮定は間違っています。非ジェネリックコレクションクラスに関する発言を誤解しているかもしれません。
  3. これは彼の試験にはなりません。
関連する問題