Skip to content

Instantly share code, notes, and snippets.

@wrobstory
Last active December 13, 2019 20:11
Show Gist options
  • Save wrobstory/06471b5cd9046a6e50e0 to your computer and use it in GitHub Desktop.
Save wrobstory/06471b5cd9046a6e50e0 to your computer and use it in GitHub Desktop.
Fastest Clojure Sum
;; Gaussian sum!
user=> (crit/with-progress-reporting (crit/quick-bench (/ (* (+ 1 99999) 99999) 2)))
Warming up for JIT optimisations 5000000000 ...
compilation occured before 333366 iterations
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 8.548926352381509 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 11240538 in 6 samples of 1873423 calls.
Execution time mean : 52.395433 ns
Execution time std-deviation : 2.054323 ns
Execution time lower quantile : 50.231213 ns ( 2.5%)
Execution time upper quantile : 54.455299 ns (97.5%)
Overhead used : 1.815229 ns
nil
;; Using hiphip
user=> (require '[hiphip.int :as hhi])
nil
user=> (def myarr (int-array (vec (range 100000))))
#'user/myarr
user=> (crit/with-progress-reporting (crit/quick-bench (hhi/asum myarr)))
Warming up for JIT optimisations 5000000000 ...
compilation occured before 3832 iterations
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 7.415712661928405 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 4938 in 6 samples of 823 calls.
Execution time mean : 124.011372 µs
Execution time std-deviation : 4.272651 µs
Execution time lower quantile : 118.886423 µs ( 2.5%)
Execution time upper quantile : 129.324151 µs (97.5%)
Overhead used : 1.792167 ns
nil
;; Sum with just longs, no sequences involved
(defn no-sequence-sum
[n]
(loop [sum 0
idx 0]
(if (= n idx)
sum
(recur (+ sum idx) (+ idx 1)))))
user=> (crit/with-progress-reporting (crit/quick-bench (no-sequence-sum 100000)))
Warming up for JIT optimisations 5000000000 ...
compilation occured before 908 iterations
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 6.90566166470177 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 612 in 6 samples of 102 calls.
Execution time mean : 1.111064 ms
Execution time std-deviation : 118.703116 µs
Execution time lower quantile : 991.262892 µs ( 2.5%)
Execution time upper quantile : 1.269477 ms (97.5%)
Overhead used : 1.815229 ns
nil
;; Materialized vector
user=> (def materialized (vec (range 100000)))
#'user/materialized
user=> (crit/with-progress-reporting (crit/quick-bench (apply + materialized)))
Warming up for JIT optimisations 5000000000 ...
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 7.52008759758524 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 420 in 6 samples of 70 calls.
Execution time mean : 1.471013 ms
Execution time std-deviation : 194.474833 µs
Execution time lower quantile : 1.249584 ms ( 2.5%)
Execution time upper quantile : 1.745316 ms (97.5%)
Overhead used : 1.792167 ns
nil
;; Lazy sequence
user=> (crit/with-progress-reporting (crit/quick-bench (apply + (range 100000))))
Warming up for JIT optimisations 5000000000 ...
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 7.847351306851401 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 150 in 6 samples of 25 calls.
Execution time mean : 4.469152 ms
Execution time std-deviation : 312.253202 µs
Execution time lower quantile : 4.057078 ms ( 2.5%)
Execution time upper quantile : 4.829578 ms (97.5%)
Overhead used : 1.792167 ns
nil
;; Loop-recur with a lazy seq
(defn loop-rest-seq-lazy
[n]
(loop [values (range n)
sum 0]
(if (seq values)
(recur (rest values) (+ (first values) sum))
sum)))
user=> (crit/with-progress-reporting (crit/quick-bench (loop-rest-seq-lazy 100000)))
Warming up for JIT optimisations 5000000000 ...
compilation occured before 145 iterations
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 9.248231825502144 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 90 in 6 samples of 15 calls.
Execution time mean : 6.906065 ms
Execution time std-deviation : 488.458909 µs
Execution time lower quantile : 6.521465 ms ( 2.5%)
Execution time upper quantile : 7.479265 ms (97.5%)
Overhead used : 1.815229 ns
nil
;; Loop-recur with a materialized vector
(defn loop-rest-vec-materialized
[vec-matl]
(loop [values vec-matl
sum 0]
(if (seq values)
(recur (rest values) (inc sum))
sum)))
user=> (crit/with-progress-reporting (crit/quick-bench (loop-rest-vec-materialized (vec (range 100000)))))
Warming up for JIT optimisations 5000000000 ...
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 8.718436050041415 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 72 in 6 samples of 12 calls.
Execution time mean : 7.078457 ms
Execution time std-deviation : 575.792983 µs
Execution time lower quantile : 6.348332 ms ( 2.5%)
Execution time upper quantile : 7.831707 ms (97.5%)
Overhead used : 1.815229 ns
nil
;; hiphip array iteration with an atom
(defn sum-swap
[n]
(let [a (atom (int 0))
int-arr (int-array (vec (range n)))]
(hhi/doarr [[i x] int-arr]
(swap! a #(+ % i)))
@a))
user=> (crit/with-progress-reporting (crit/quick-bench (sum-swap 100000)))
Warming up for JIT optimisations 5000000000 ...
compilation occured before 61 iterations
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 8.301125168634051 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 72 in 6 samples of 12 calls.
Execution time mean : 9.390207 ms
Execution time std-deviation : 1.039785 ms
Execution time lower quantile : 8.413832 ms ( 2.5%)
Execution time upper quantile : 10.598134 ms (97.5%)
Overhead used : 1.815229 ns
nil
@mrocklin
Copy link

FWIW

In [1]: import numpy as np

In [2]: x = np.arange(100000)

In [3]: %timeit x.sum()
10000 loops, best of 3: 54.1 µs per loop

In [4]: %timeit np.arange(100000).sum()
10000 loops, best of 3: 170 µs per loop

@wrobstory
Copy link
Author

The results if I include the allocation are grim:

user=> (crit/with-progress-reporting (crit/quick-bench (hhi/asum (int-array (vec (range 100000))))))
Warming up for JIT optimisations 5000000000 ...
  compilation occured before 179 iterations
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
WARNING: Final GC required 8.828917727723212 % of runtime
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 102 in 6 samples of 17 calls.
             Execution time mean : 6.347498 ms
    Execution time std-deviation : 488.073756 µs
   Execution time lower quantile : 5.833998 ms ( 2.5%)
   Execution time upper quantile : 6.987631 ms (97.5%)
                   Overhead used : 1.815229 ns
nil

C: still really fast!

@wrobstory
Copy link
Author

julia> function add_things()
         sum = 0
         for i = 1:100000
           sum += i
         end
         sum
       end
add_things (generic function with 1 method)

julia> benchmark(add_things, "", "", 10000)
1x12 DataFrame
| Row | Category | Benchmark | Iterations | TotalWall  | AverageWall | MaxWall   | MinWall |
|-----|----------|-----------|------------|------------|-------------|-----------|---------|
| 1   | ""       | ""        | 10000      | 0.00252439 | 2.52439e-7  | 1.7001e-5 | 2.11e-7 |

| Row | Timestamp             | JuliaHash                                  | CodeHash | OS       | CPUCores |
|-----|-----------------------|--------------------------------------------|----------|----------|----------|
| 1   | "2014-12-13 15:42:50" | "b24213b893ace6ca601722f6cdaac15f2b034b7b" | NA       | "Darwin" | 8        |

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment