Note that there are some explanatory texts on larger screens.

plurals
  1. POInterpreting a benchmark in C, Clojure, Python, Ruby, Scala and others
    primarykey
    data
    text
    <h2><strong>Disclaimer</strong></h2> <p>I know that artificial benchmarks are evil. They can show results only for very specific narrow situation. I don't assume that one language is better than the other because of the some stupid bench. However I wonder why results is so different. Please see my questions at the bottom.</p> <h2>Math benchmark description</h2> <p>Benchmark is simple math calculations to find pairs of prime numbers which differs by 6 (so called <a href="https://en.wikipedia.org/wiki/Sexy_prime" rel="noreferrer">sexy primes</a>) E.g. sexy primes below 100 would be: <code>(5 11) (7 13) (11 17) (13 19) (17 23) (23 29) (31 37) (37 43) (41 47) (47 53) (53 59) (61 67) (67 73) (73 79) (83 89) (97 103)</code></p> <h2>Results table</h2> <p><em>In table: calculation time in seconds</em> Running: all except Factor was running in VirtualBox (Debian unstable amd64 guest, Windows 7 x64 host) CPU: AMD A4-3305M</p> <pre><code> Sexy primes up to: 10k 20k 30k 100k Bash 58.00 200.00 [*1] [*1] C 0.20 0.65 1.42 15.00 Clojure1.4 4.12 8.32 16.00 137.93 Clojure1.4 (optimized) 0.95 1.82 2.30 16.00 Factor n/a n/a 15.00 180.00 Python2.7 1.49 5.20 11.00 119 Ruby1.8 5.10 18.32 40.48 377.00 Ruby1.9.3 1.36 5.73 10.48 106.00 Scala2.9.2 0.93 1.41 2.73 20.84 Scala2.9.2 (optimized) 0.32 0.79 1.46 12.01 </code></pre> <p>[*1] - I'm afraid to imagine how much time will it take<br></p> <h2>Code listings</h2> <p>C:</p> <pre><code>int isprime(int x) { int i; for (i = 2; i &lt; x; ++i) if (x%i == 0) return 0; return 1; } void findprimes(int m) { int i; for ( i = 11; i &lt; m; ++i) if (isprime(i) &amp;&amp; isprime(i-6)) printf("%d %d\n", i-6, i); } main() { findprimes(10*1000); } </code></pre> <p>Ruby:</p> <pre><code>def is_prime?(n) (2...n).all?{|m| n%m != 0 } end def sexy_primes(x) (9..x).map do |i| [i-6, i] end.select do |j| j.all?{|j| is_prime? j} end end a = Time.now p sexy_primes(10*1000) b = Time.now puts "#{(b-a)*1000} mils" </code></pre> <p>Scala:</p> <pre><code>def isPrime(n: Int) = (2 until n) forall { n % _ != 0 } def sexyPrimes(n: Int) = (11 to n) map { i =&gt; List(i-6, i) } filter { _ forall(isPrime(_)) } val a = System.currentTimeMillis() println(sexyPrimes(100*1000)) val b = System.currentTimeMillis() println((b-a).toString + " mils") </code></pre> <p>Scala opimized <code>isPrime</code> (the same idea like in Clojure optimization):</p> <pre><code>import scala.annotation.tailrec @tailrec // Not required, but will warn if optimization doesn't work def isPrime(n: Int, i: Int = 2): Boolean = if (i == n) true else if (n % i != 0) isPrime(n, i + 1) else false </code></pre> <p>Clojure:</p> <pre><code>(defn is-prime? [n] (every? #(&gt; (mod n %) 0) (range 2 n))) (defn sexy-primes [m] (for [x (range 11 (inc m)) :let [z (list (- x 6) x)] :when (every? #(is-prime? %) z)] z)) (let [a (System/currentTimeMillis)] (println (sexy-primes (* 10 1000))) (let [b (System/currentTimeMillis)] (println (- b a) "mils"))) </code></pre> <p>Clojure optimized <code>is-prime?</code>:</p> <pre><code>(defn ^:static is-prime? [^long n] (loop [i (long 2)] (if (= (rem n i) 0) false (if (&gt;= (inc i) n) true (recur (inc i)))))) </code></pre> <p>Python</p> <pre><code>import time as time_ def is_prime(n): return all((n%j &gt; 0) for j in xrange(2, n)) def primes_below(x): return [[j-6, j] for j in xrange(9, x+1) if is_prime(j) and is_prime(j-6)] a = int(round(time_.time() * 1000)) print(primes_below(10*1000)) b = int(round(time_.time() * 1000)) print(str((b-a)) + " mils") </code></pre> <p>Factor</p> <pre><code>MEMO:: prime? ( n -- ? ) n 1 - 2 [a,b] [ n swap mod 0 &gt; ] all? ; MEMO: sexyprimes ( n n -- r r ) [a,b] [ prime? ] filter [ 6 + ] map [ prime? ] filter dup [ 6 - ] map ; 5 10 1000 * sexyprimes . . </code></pre> <p>Bash(zsh):</p> <pre><code>#!/usr/bin/zsh function prime { for (( i = 2; i &lt; $1; i++ )); do if [[ $[$1%i] == 0 ]]; then echo 1 exit fi done echo 0 } function sexy-primes { for (( i = 9; i &lt;= $1; i++ )); do j=$[i-6] if [[ $(prime $i) == 0 &amp;&amp; $(prime $j) == 0 ]]; then echo $j $i fi done } sexy-primes 10000 </code></pre> <h2>Questions</h2> <ol> <li>Why Scala is so fast? Is it because of <strong>static typing</strong>? Or it is just using JVM very efficiently?</li> <li><s>Why such a huge difference between Ruby and Python? I thought these two are not somewhat totally different. Maybe my code is wrong. Please enlighten me! Thanks.</s> <strong>UPD</strong> Yes, that was error in my code. Python and Ruby 1.9 are pretty equal.</li> <li>Really impressive jump in productivity between Ruby versions.</li> <li>Can I optimize Clojure code by adding type declarations? Will it help?</li> </ol>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload