11

Vector2 の Generated のリストがあり、それらが存在するかどうかを確認するために辞書と照合する必要があります。この関数はティックごとに実行されます。

どちらが最も速く実行されますか/この方法で実行する方が良いですか?

    public static bool exists(Vector2 Position, Dictionary<Vector2, object> ToCheck)
    {
        try
        {
            object Test = ToCheck[Position];
            return (true);
        }
        catch 
        {
            return (false);
        }           
    }

それとも、標準に固執する必要がありますか?

    public static bool exists(Vector2 Position, Dictionary<Vector2, object> ToCheck)
    {
        if (ToCheck.ContainsKey(Position))
        {
            return (true);
        }
        return (false);
    }

入力していただきありがとうございます:)

補足: (キーの値はこの時点では問題にならないか、ContainsKey の代わりに TryGetValue を使用します)

4

4 に答える 4

28

私はそれが古い質問であることを知っていますが、経験的なデータを少し追加するだけです...

10,000 エントリの辞書で 50,000,000 回のルックアップを実行し、完了するまでの相対時間を比較します。

..すべてのルックアップが成功した場合:

  • まっすぐな (チェックされていない) 実行には 1.2 秒かかります
  • 保護された (ContainsKey) 実行には 2 秒かかります
  • 処理された (try-catch) 実行には 1.21 秒かかります

..10,000回のルックアップごとに1回失敗した場合:

  • 保護された (ContainsKey) 実行には 2 秒かかります
  • 処理された (try-catch) 実行には 1.37 秒かかります

..10,000 回のルックアップのうち 16 回が失敗した場合:

  • 保護された (ContainsKey) 実行には 2 秒かかります
  • 処理された (try-catch) 実行には 3.27 秒かかります

..10,000 回のルックアップのうち 250 回が失敗した場合:

  • 保護された (ContainsKey) 実行には 2 秒かかります
  • 処理された (try-catch) 実行には 32 秒かかります

..したがって、保護されたテストは一定のオーバーヘッドを追加しますが、それ以上のことはありません.try-catch テストは、失敗しない場合はテストなしとほぼ同じ速度で動作しますが、失敗の数に比例してパフォーマンスが低下します。

テストの実行に使用したコード:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
   class Program
   {
      static void Main(string[] args)
      {  Test(0);
         Test(1);
         Test(16);
         Test(250);
      }

      private static void Test(int failsPerSet)
      {  Dictionary<int, bool> items = new Dictionary<int,bool>();

         for(int i =  0; i < 10000; i++)
            if(i >= failsPerSet)
               items[i] = true;

         if(failsPerSet == 0)
            RawLookup(items, failsPerSet);

         GuardedLookup(items, failsPerSet);

         CaughtLookup(items, failsPerSet);

      }

      private static void RawLookup
      (  Dictionary<int, bool> items
      ,  int             failsPerSet
      ){ int                   found = 0;
         DateTime              start ;

         Console.Write("Raw     (");
         Console.Write(failsPerSet);
         Console.Write("): ");

         start = DateTime.Now;
         for(int i = 0; i < 50000000; i++)
         {  int pick = i % 10000;
            if(items[pick])
               found++;
         }

         Console.WriteLine(DateTime.Now - start);
      }

      private static void GuardedLookup
      (  Dictionary<int, bool> items
      ,  int             failsPerSet
      ){ int                   found = 0;
         DateTime              start ;

         Console.Write("Guarded (");
         Console.Write(failsPerSet);
         Console.Write("): ");

         start = DateTime.Now;
         for(int i = 0; i < 50000000; i++)
         {  int pick = i % 10000;
            if(items.ContainsKey(pick))
               if(items[pick])
                  found++;
         }

         Console.WriteLine(DateTime.Now - start);
      }

      private static void CaughtLookup
      (  Dictionary<int, bool> items
      ,  int             failsPerSet
      ){ int                   found = 0;
         DateTime              start ;

         Console.Write("Caught  (");
         Console.Write(failsPerSet);
         Console.Write("): ");

         start = DateTime.Now;
         for(int i = 0; i < 50000000; i++)
         {  int pick = i % 10000;
            try
            {  if(items[pick])
                  found++;
            }
            catch
            {  
            }
         }

         Console.WriteLine(DateTime.Now - start);
      }

   }
}
于 2012-11-02T12:05:47.300 に答える
18

必ずチェックを使用してContainsKeyください。例外処理により、大きなオーバーヘッドが追加される可能性があります。

例外をスローすると、パフォーマンスに悪影響を及ぼす可能性があります。定期的に失敗するコードについては、デザイン パターンを使用してパフォーマンスの問題を最小限に抑えることができます。

例外は、チェックできる条件に使用するためのものではありません。

例外全般、特に例外処理に関する MSDN ドキュメントを読むことをお勧めします。

于 2012-09-14T00:45:57.573 に答える
0

通常のプログラム パスの一部として try/catch を使用しないでください。これは非常にコストがかかり、防止できないエラーのみをキャッチする必要があります。ここに行く方法は、ContainsKey です。

補足: いいえ。値が重要な場合は、ContainsKey が存在するかどうかを確認し、存在する場合は取得します。トライ/キャッチしない。

于 2012-09-14T00:48:24.730 に答える
0

補足: (キーの値はこの時点では問題にならないか、ContainsKey の代わりに TryGetValue を使用します)

あなたが受け入れた答えは正しいですが、値ではなくキーのみを気にする場合はHashSet、 ? ではなくDictionary?を探しているのかもしれません。

さらに、2 番目のコード スニペットは、文字通りゼロの値を追加するメソッドです。そのToCheck.ContainsKey(Position)メソッドを呼び出してその値を返すだけで他に何もしないメソッドを作成しないでください。

于 2012-09-14T02:26:39.923 に答える