Taqmuraz / speed-table

1 stars 0 forks source link

Clojure? #1

Open licht1stein opened 13 hours ago

licht1stein commented 13 hours ago

I have doubts about the declared clojure results and I don't see the clojure source file to reproduce. Is it in the repo?

UPDATE: This is a comment thread to the article https://dev.to/taqmuraz/c-and-c-are-really-so-fast-5gf1

Taqmuraz commented 12 hours ago

I appreciate your interest. I tested clojure running this code in the REPL (time (reduce #(+ %1 %2) (range 1000000000))) Now I added the same code to the repo. I use lambda expression instead of just +, because Clojure compiler does infer types in lambdas, so they are evaluated faster.

licht1stein commented 12 hours ago

Well, try this. Not the fastest way, but it will be 10 times or so faster.

(time
   (loop [acc 0
          x 1]
     (if (< x 1000000000)
       (recur (unchecked-add acc x) (unchecked-add x 1))
       acc)))

Also you can always just wrap Java. It will have a small penalty, but will still be faster than most of the rating:


user
> (time (.sum (LongStream/range 0 1000000000)))
"Elapsed time: 3081.191999 msecs"
499999999500000000
user
> (time (.sum (LongStream/range 0 1000000000)))
"Elapsed time: 783.588162 msecs"
499999999500000000
user
> (time (.sum (LongStream/range 0 1000000000)))
"Elapsed time: 475.763772 msecs"
499999999500000000
licht1stein commented 12 hours ago

This should be quite close to results in Java, so please correct the rating in the article:

(time
    (loop [acc 0 x 1]
      (if (< x 1000000000)
        (recur (unchecked-add acc x) (unchecked-inc x))
        acc)))
Taqmuraz commented 11 hours ago

Thank you very much for this example. It is a discovery for me, that Clojure code may be so fast, though I know it is being compiled. I did not use Java classes, such as LongStream, because for me it would be same as benchmarking Java.

Taqmuraz commented 11 hours ago

I wonder could I contact you somehow to ask some questions about Clojure?

licht1stein commented 11 hours ago

Here are the final benchmarks on my machine, using criterium benchmarking library on Clojure 1.12.0:

Your original code:

(crit/quick-bench
    (reduce #(+ %1 %2) (range 1000000000)))

  ;; Evaluation count : 6 in 6 samples of 1 calls.
  ;;            Execution time mean : 7.285339 sec
  ;;   Execution time std-deviation : 146.413262 ms
  ;;  Execution time lower quantile : 7.195585 sec ( 2.5%)
  ;;  Execution time upper quantile : 7.528866 sec (97.5%)
  ;;                  Overhead used : 1.827446 ns

Optimized Clojure code (courtesy of @andreyorst and @serioga):

  (crit/quick-bench
    (loop [acc 0 x 1]
      (if (< x 1000000000)
        (recur (unchecked-add acc x) (unchecked-inc x))
        acc)))

  ;; Evaluation count : 6 in 6 samples of 1 calls.
  ;;              Execution time mean : 214.212103 ms
  ;;     Execution time std-deviation : 2.277072 ms
  ;;    Execution time lower quantile : 211.700958 ms ( 2.5%)
  ;;    Execution time upper quantile : 217.234564 ms (97.5%)
  ;;                    Overhead used : 1.827446 ns

Java interop:

  (crit/quick-bench
    (.sum (java.util.stream.LongStream/range 0 1000000000))))

;; Evaluation count : 6 in 6 samples of 1 calls.
;;              Execution time mean : 207.908504 ms
;;     Execution time std-deviation : 1.909420 ms
;;    Execution time lower quantile : 206.375843 ms ( 2.5%)
;;    Execution time upper quantile : 210.771871 ms (97.5%)
;;                    Overhead used : 1.827446 ns,

I did not use Java classes, such as LongStream, because for me it would be same as benchmarking Java.

It's great that you brought this up, since you put Java on first place in your rating. And according to the benchmarking interop and optimized Clojure code, interop was just 7ms quicker: 214ms for optimized Clojure code and 207ms for Java interop code.

Which means that you should put Clojure close to Java in your original article. I don't know if you benchmarked C correctly -- I'm not a C programmer, but I'd like to put Clojure in it's rightful place of not only being a pleasure to code with, but also being quite bloody fast when :)

And sure, you can contact me for Clojure questions.

Taqmuraz commented 11 hours ago

On my machine your Clojure code took 373ms to run. I hope, I benchmarked C code wrong, though I am waiting for critics from C programmers. I would say, Rust surprised me, but it was a challenge to make rustc play by the rules. And, yes, I could not even imagine such performance from Clojure, even knowing it actively uses JIT compiler.

Please, give me your preferred contact, because I can't see one in your github profile. It may be discord, skype, telegram or what you prefer.