title: Faster poker hand evaluation
body: <p>I'm trying to use "RayW hand evaluator" approach to get a card combination score (5 best cards out of 7). However I'm having some <strong>performance issues</strong> with this method. According to sources - using this approach it must be possible to evaluate more than 300 mil hands per second! My result is 10 mills in 1.5 seconds, which is many times slower.</p>
  
  <p>The idea behind "RayW hand evaluator" is following:</p>
  
  <blockquote>
    <p>The Two Plus Two evaluator consists of a large lookup table containing
    some thirty-two million entries (32,487,834 to be precise). In order
    to lookup a given 7-card poker hand, you trace a path through this
    table, performing one lookup per card. When you get to the last card,
    the value so obtained is the official equivalence value of the hand</p>
  </blockquote>
  
  <p>here is how code looks like:</p>
  
  <pre><code>namespace eval
  {
  public struct TPTEvaluator
  {
      public static int[] _lut;
  
      public static unsafe void Init() // to load a table
      {
          _lut = new int[32487834];
          FileInfo lutFileInfo = new FileInfo("HandRanks.dat");
          if (!lutFileInfo.Exists)
          {throw new Exception("Handranks.dat not found");}
  
          FileStream lutFile = new FileStream("HandRanks.dat", FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096);
  
          byte[] tempBuffer = new byte[32487834 * 4];
          lutFile.Read(tempBuffer, 0, 32487834 * 4);
  
          fixed (int* pLut = _lut)
          { Marshal.Copy(tempBuffer, 0, (IntPtr)pLut, 32487834 * 4);}
          tempBuffer = null;
      }
  
      public unsafe static int LookupHand(int[] cards) // to get a hand strength
      {
          fixed (int* pLut = _lut)
          {
              int p = pLut[53 + cards[0]];
              p = pLut[p + cards[1]];
              p = pLut[p + cards[2]];
              p = pLut[p + cards[3]];
              p = pLut[p + cards[4]];
              p = pLut[p + cards[5]];
              return pLut[p + cards[6]];
          }
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <p>and that's how I test this approach:</p>
  
  <pre><code>    private void button4_Click(object sender, EventArgs e)
      {
          int[] str = new int[] { 52, 34, 25, 18, 1, 37, 22 };
  
          int r1 = 0;
  
          DateTime now = DateTime.Now;
          for (int i = 0; i &lt; 10000000; i++) // 10 mil iterations 1.5 - 2 sec
          { r1 = TPTEvaluator.LookupHand(str);} // here
          TimeSpan s1 = DateTime.Now - now;
          textBox14.Text = "" + s1.TotalMilliseconds;
      }
  </code></pre>
  
  <p>I believe that this method was originally implemented in C++, but nevertheless C# port should work faster. <strong>Is there any way how I can get close to at least 100 millions of hands in one sec?</strong></p>
  
  <p>What I tried so far:</p>
  
  <ul>
  <li>tried using Static, and non-static methods - no difference.</li>
  <li><p>tried using dictionary lookup instead of array</p>
  
  <pre><code>public void ArrToDict(int[] arr, Dictionary&lt;int, int&gt; dic)
  {
      for (int i = 0; i &lt; arr.Length; i++)
      {
          dic.Add(i, arr[i]);
      }
  }
  
  public unsafe static int LookupHandDict(int[] cards)
  {
      int p = dict[53 + cards[0]];
      p = dict[p + cards[1]];
      p = dict[p + cards[2]];
      p = dict[p + cards[3]];
      p = dict[p + cards[4]];
      p = dict[p + cards[5]];
      return dict[p + cards[6]];
  }
  </code></pre></li>
  </ul>
  
  <p>Elapsed time for 10 mills of hands is almost 6 times slower..</p>
  
  <ul>
  <li><p>According to one person - he increased the performance by 200 mills by removing "unsafe" code. I tried to do the same thing but results are almost the same.</p>
  
  <pre><code>public static int LookupHand(int[] cards)
  {
          int p = _lut[53 + cards[0]];
          p = _lut[p + cards[1]];
          p = _lut[p + cards[2]];
          p = _lut[p + cards[3]];
          p = _lut[p + cards[4]];
          p = _lut[p + cards[5]];
          return _lut[p + cards[6]];
  }
  </code></pre></li>
  </ul>
  
  <p>Here is the quote:</p>
  
  <blockquote>
    <p>After removing the "unsafe" code parts and some small adjustments in
    the c# version it is now also around 310 mio.</p>
  </blockquote>
  
  <p>is there any other way to increase the performance of this hand ranking system?</p>