Interpreting a benchmark in C, Clojure, Python, Ruby, Scala and others
Rough answers:
- Scala's static typing is helping it quite a bit here - this means that it uses the JVM pretty efficiently without too much extra effort.
- I'm not exactly sure on the Ruby/Python difference, but I suspect that
(2...n).all?
in the functionis-prime?
is likely to be quite well optimised in Ruby (EDIT: sounds like this is indeed the case, see Julian's answer for more detail...) - Ruby 1.9.3 is just much better optimised
- Clojure code can certainly be accelerated a lot! While Clojure is dynamic by default, you can use type hints, primitive maths etc. to get close to Scala / pure Java speed in many cases when you need to.
Most important optimisation in the Clojure code would be to use typed primitive maths within is-prime?
, something like:
(set! *unchecked-math* true) ;; at top of file to avoid using BigIntegers
(defn ^:static is-prime? [^long n]
(loop [i (long 2)]
(if (zero? (mod n i))
false
(if (>= (inc i) n) true (recur (inc i))))))
With this improvement, I get Clojure completing 10k in 0.635 secs (i.e. the second fastest on your list, beating Scala)
P.S. note that you have printing code inside your benchmark in some cases - not a good idea as it will distort the results, especially if using a function like print
for the first time causes initialisation of IO subsystems or something like that!
Are there any good Clojure benchmarks?
See jafingerhut / clojure-benchmarks
iirc the current clojure implementation has not been focussed on performance, but the next version supposedly will.
On Performance and Java Interoperability: Clojure vs. Scala
I think either language will be fast enough for you. When comparing Python and Java, it seems a bit unreasonable to blame the language for the speed difference. Java is compiled JIT (except on mobile devices*) whereas Python is interpreted. Just because both use a bytecode does not mean the implementations will have even remotely comparable performance. But both Scala and Clojure are JVM languages so they should have similar performance.
Scala has a few implementation advantages over Clojure and I would expect somewhat higher performance. Although Scala's static typing would normally translate into a speed advantage over Clojure's duck typing, Clojure does support type hinting which can speed up code considerably. Possibly, ordinary Scala is faster than ordinary Clojure, but you only need to optimize the bottlenecks. Most of a program's run time is generated by a small amount of the actual code.
Regarding interop w/ Java, Scala is closer to Java but I'm sure both languages interoperate well. In Programming Clojure Stuart Halloway writes: "[you can access] anything you could reach from Java code.".
And since Scala author Martin Odersky wrote Sun's Java compiler, I kinda think no balls have been dropped on the Scala side, either. :-)
You would be hard-pressed to pick two better languages, though I like Ruby also. Why are you worried about which one to try? Why not try them both? Scala is more likely to be "the next Java", while it's hard to imagine that Lisp will finally take off after not doing so for over 50 years. But it's clear that Lisp is on its own unique level of abstraction, and Clojure is fairly simple, so Scala + Clojure won't be that much harder than just (the rather complex) Scala and I'm sure you will be glad you did it.
And for that matter they interoperate...
* dalvik (android's JVM) got a JIT compiler in 2.2 version in 2010
Why is the Clojure Hello World program so slow compared to Java and Python?
You're not measuring much here except for Clojure boot time. You're also running your program in such a way that you are measuring compilation time as well. If you want to see faster load times you'll need to ahead-of-time compile your code.
Having coded a bit in Python, I've found that Clojure is as a general rule much, much, much faster than Python and you can usually get a Clojure program to get within 2X-4X of the speed of pure Java.
How to optimize for-comprehensions and loops in Scala?
The problem in this particular case is that you return from within the for-expression. That in turn gets translated into a throw of a NonLocalReturnException, which is caught at the enclosing method. The optimizer can eliminate the foreach but cannot yet eliminate the throw/catch. And throw/catch is expensive. But since such nested returns are rare in Scala programs, the optimizer did not yet address this case. There is work going on to improve the optimizer which hopefully will solve this issue soon.
Related Topics
Matplotlib: Specify Format of Floats for Tick Labels
Pandas New Column from Groupby Averages
In Python, How to Capture the Stdout from a C++ Shared Library to a Variable
Add Custom CSS Styling to Model Form Django
Dealing with the Class Imbalance in Binary Classification
Python Equivalent of Ruby's Each_Slice(Count)
Swift Playground Error: Module 'Python' Has No Member Named 'Import'
How to Access the Request Object or Any Other Variable in a Form's Clean() Method
How to Delete the Contents of a Folder
How to Split a Multi-Line String into Multiple Lines
What Is the Purpose of _Str_ and _Repr_
Inverting a Dictionary with List Values
Python Code to Remove HTML Tags from a String
Best Way to Set Entry Background Color in Python Gtk3 and Set Back to Default
How Can One Find the Unicode Codepoints That a Font Has Glyphs For, on a Debian-Based System
Is There a Function That Checks If a Character in a String Is a Letter in the Alphabet? (Swift)