title: Can this Crystal benchmark code be improved significantly?
body: <p>I'm deciding on a language to use for back-end use. I've looked at Go, Rust, C++, and I thought I'd look at Crystal because it did reasonably well in some benchmarks. Speed is not the ultimate requirement, however speed is important. The syntax is equally important, and I'm not averse to the Crystal syntax. The simple benchmark that I wrote is only a small part of the evaluation and it's also partly familiarisation. I'm using Windows, so I'm using Crystal 0.35.1 on Win10 2004-19041.329 with WSL2 and Ubuntu 20.04 LTS. I don't know if WSL2 has any impact on performance. The benchmark is primarily using integer arithmetic. Go, Rust, and C++ have almost equal performance to each other (on Win10). I've translated that code to Crystal, and it runs a fair bit slower than those three. Out of simple curiosity I also ran the code on Dart (on Win10), and it ran (very surprisingly) almost twice as fast as those three. I do understand that a simple benchmark does not say a lot. I notice from a recent post that Crystal is more efficient with floats than integers, however this was and is aimed at integers.</p>
  <p>This is my first Crystal program, so I thought I should ask - is there any simple improvements I can make to the code for performance? I don't want to improve the algorithm other than to correct errors, because all are using this algorithm.</p>
  <p>The code is as follows:</p>
  <pre><code># ------ Prime-number counter. -----#
  
  # Brian      25-Jun-2020       Program written - my first Crystal program.
  
  # -------- METHOD TO CALCULATE APPROXIMATE SQRT ----------#
  
  def fnCalcSqrt(iCurrVal)  # Calculate approximate sqrt
    iPrevDiv = 0.to_i64
    iDiv = (iCurrVal // 10)
    if iDiv &lt; 2
      iDiv = 2
    end
    while (true)
      begin
        iProd = (iDiv * iDiv)
      rescue vError
        puts &quot;Error = #{vError}, iDiv = #{iDiv}, iCurrVal = #{iCurrVal}&quot;
        exit
      end
      if iPrevDiv &lt; iDiv
        iDiff = ((iDiv - iPrevDiv) // 2)
      else
        iDiff = ((iPrevDiv - iDiv) // 2)
      end
  
      iPrevDiv = iDiv
  
      if iProd &lt; iCurrVal # iDiv IS TOO LOW #
        if iDiff &lt; 1
          iDiff = 1
        end
        iDiv += iDiff
      else
        if iDiff &lt; 2
          return iDiv
        end
        iDiv -= iDiff
      end
    end
  end
  
  # ---------- PROGRAM MAINLINE --------------#
  
  print &quot;\nCalculate Primes from 1 to selected number&quot;
  #iMills = uninitialized Int32   # CHANGED THIS BECAUSE IN --release DOES NOT WORK
  iMills = 0.to_i32
  while iMills &lt; 1 || iMills &gt; 100
    print &quot;\nEnter the ending number of millions (1 to 100) : &quot;
    sInput = gets
    if sInput == &quot;&quot;
      exit
    end
    iTemp = sInput.try &amp;.to_i32?
    if !iTemp
      puts &quot;Please enter a valid number&quot;
      puts &quot;iMills = #{iTemp}&quot;
    elsif iTemp &gt; 100   # &gt; 100m
      puts &quot;Invalid - too big must be from 1 to 100 (million)&quot;
    elsif iTemp &lt; 1
      puts &quot;Invalid - too small - must be from 1 to 100 (million)&quot;
    else
      iMills = iTemp
    end
  end
  
  #iCurrVal = 2   # THIS CAUSES ARITHMETIC OVERFLOW IN SQRT CALC.
  iCurrVal = 2.to_i64
  iEndVal = iMills * 1_000_000
  iPrimeTot = 0
  
  # ----- START OF PRIME NUMBER CALCULATION -----#
  
  sEndVal = iEndVal.format(',', group: 3) # =&gt; eg. &quot;10,000,000&quot;
  puts &quot;Calculating number of prime numbers from 2 to #{sEndVal} ......&quot;
  vStartTime = Time.monotonic
  while iCurrVal &lt;= iEndVal
    if iCurrVal % 2 != 0 || iCurrVal == 2
      iSqrt = fnCalcSqrt(iCurrVal)
      tfPrime = true  # INIT
      iDiv = 2
      while iDiv &lt;= iSqrt
        if ((iCurrVal % iDiv) == 0)
          tfPrime = (iDiv == iCurrVal);
          break;
        end
        iDiv += 1
      end
      if (tfPrime)
        iPrimeTot+=1;
      end
    end
    iCurrVal += 1
  end
  puts &quot;Elapsed time = #{Time.monotonic - vStartTime}&quot;
  puts &quot;prime total = #{iPrimeTot}&quot;
  
  </code></pre>