Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

First of all I would like to make it clear that this is not a language-X-versus-language-Y question to determine which is better.

I have been using Java for a long time and I intend to keep using it. Parallel to this, I am currently learning Scala with great interest: apart from minor things that take some getting used to my impression is that I can really work very well in this language.

My question is: how does software written in Scala compare to software written in Java in terms of execution speed and memory consumption? Of course, this is a difficult question to answer in general, but I would expect that higher level constructs such as pattern matching, higher-order functions, etc, introduce some overhead.

However, my current experience in Scala is limited to small examples under 50 lines of code and I haven't run any benchmarks up to now. So, I have no real data.

If it turned out that Scala does have some overhead wrt Java, does it make sense to have mixed Scala / Java projects, where one codes the more complex parts in Scala and the performance-critical parts in Java? Is this a common practice?

EDIT 1

I have run a small benchmark: build a list of integers, multiply each integer by two and put it in a new list, print the resulting list. I wrote a Java implementation (Java 6) and a Scala implementation (Scala 2.9). I have run both on Eclipse Indigo under Ubuntu 10.04.

The results are comparable: 480 ms for Java and 493 ms for Scala (averaged over 100 iterations). Here are the snippets I have used.

// Java
public static void main(String[] args)
{
    long total = 0;
    final int maxCount = 100;
    for (int count = 0; count < maxCount; count++)
    {
        final long t1 = System.currentTimeMillis();

        final int max = 20000;
        final List<Integer> list = new ArrayList<Integer>();
        for (int index = 1; index <= max; index++)
        {
            list.add(index);
        }

        final List<Integer> doub = new ArrayList<Integer>();
        for (Integer value : list)
        {
            doub.add(value * 2);
        }

        for (Integer value : doub)
        {
            System.out.println(value);
        }

        final long t2 = System.currentTimeMillis();

        System.out.println("Elapsed milliseconds: " + (t2 - t1));
        total += t2 - t1;
    }

    System.out.println("Average milliseconds: " + (total / maxCount));
}

// Scala
def main(args: Array[String])
{
    var total: Long = 0
    val maxCount    = 100
    for (i <- 1 to maxCount)
    {
        val t1   = System.currentTimeMillis()
        val list = (1 to 20000) toList
        val doub = list map { n: Int => 2 * n }

        doub foreach ( println )

        val t2 = System.currentTimeMillis()

        println("Elapsed milliseconds: " + (t2 - t1))
        total = total + (t2 - t1)
    }

    println("Average milliseconds: " + (total / maxCount))
}

So, in this case it seems that the Scala overhead (using range, map, lambda) is really minimal, which is not far from the information provided by World Engineer.

Maybe there are other Scala constructs that should be used with care because they are particularly heavy to execute?

EDIT 2

Some of you pointed out that the println's in the inner loops take up most of the execution time. I have removed them and set the size of the lists to 100000 instead of 20000. The resulting average was 88 ms for Java and 49 ms for Scala.

share|improve this question
5  
I imagine that since Scala compiles to JVM byte code, then the performance could theoretically be equivalent to Java running under the same JVM all other things being equal. The difference I think is in how the Scala compiler creates the byte code and if it does so efficiently. –  maple_shaft Jan 24 '12 at 18:52
2  
@maple_shaft: Or maybe there's overhead in Scala compile time? –  FrustratedWithFormsDesigner Jan 24 '12 at 19:03
1  
@Giorgio There is no runtime distinction between Scala objects and Java objects, they are all JVM objects that are defined and behave per the byte code. Scala for instance as a language has the concept of closures, but when these are compiled they are compiled to a number of classes with byte code. Theoretically, I could physically write Java code that could compile to the exact same byte code and the runtime behavior would be exactly the same. –  maple_shaft Jan 24 '12 at 19:12
2  
@maple_shaft: That's exactly what I am aiming at: I find the above Scala code much more concise and readable than the corresponding Java code. I was just wondering if it would make sense to write parts of a Scala project in Java for performance reasons, and what those parts would be. –  Giorgio Jan 24 '12 at 20:28
2  
The runtime will be largely occupied by the println calls. You need a more compute-intensive test. –  kevin cline Jan 24 '12 at 22:03
show 8 more comments

5 Answers 5

up vote 28 down vote accepted

There's one thing that you can do concisely and efficiently in Java that you can't in Scala: enumerations. For everything else, even for constructs that are slow in Scala's library, you can get efficient versions working in Scala.

So, for the most part, you don't need to add Java to your code. Even for code that uses enumeration in Java, there's often a solution in Scala that is adequate or good -- I place the exception on enumerations that have extra methods and whose int constant values are used.

As for what to watch out for, here are some things.

  • If you use the enrich my library pattern, always convert to a class. For example:

    // WRONG -- the implementation uses reflection when calling "isWord"
    implicit def toIsWord(s: String) = new { def isWord = s matches "[A-Za-z]+" }
    
    // RIGHT
    class IsWord(s: String) { def isWord = s matches "[A-Za-z]+" }
    implicit def toIsWord(s: String): IsWord = new IsWord(s)
    
  • Be wary of collection methods -- because they are polymorphic for the most part, JVM does not optimize them. You need not avoid them, but pay attention to it on critical sections. Be aware that for in Scala is implemented through method calls and anonymous classes.

  • If using a Java class, such as String, Array or AnyVal classes that correspond to Java primitives, prefer the methods provided by Java when alternatives exist. For example, use length on String and Array instead of size.

  • Avoid careless use of implicit conversions, as you can find yourself using conversions by mistake instead of by design.

  • Extend classes instead of traits. For example, if you are extending Function1, extend AbstractFunction1 instead.

  • Use -optimise and specialization to get most of Scala.

  • Understand what is happening: javap is your friend, and so are a bunch of Scala flags that show what's going on.

  • Scala idioms are designed to improve correctness and make the code more concise and maintainable. They are not designed for speed, so if you need to use null instead of Option in a critical path, do so! There's a reason why Scala is multi-paradigm.

  • Remember that the true measure of performance is running code. See this question for an example of what may happen if you ignore that rule.

share|improve this answer
1  
+1: A lot of useful information, even on topics that I still have to learn, but it is useful to have read some hint before I get to look at them. –  Giorgio Jan 24 '12 at 22:15
    
Why first approach uses reflection ? It generates anonymous class anyway, so why don't use it instead of reflection ? –  Oleksandr.Bezhan Oct 1 '13 at 15:28
    
@Oleksandr.Bezhan Anonymous class is a Java concept, not a Scala one. It generates a type refinement. An anonymous class method that does not override its base class cannot be accessed from the outside. The same is not true of Scala's type refinements, so the only way to get at that method is through reflection. –  Daniel C. Sobral Oct 1 '13 at 17:13
add comment

According to the Benchmarks Game for a single core, 32 bit system, Scala is at a median 80% as fast as Java. The performance is approximately the same for a Quad Core x64 computer. Even memory usage and code density are very similar in most cases. I would say based on these (rather unscientific) analyses that you are correct in asserting that Scala adds some overhead to Java. It does not appear to add tons of overhead so I'd suspect the diagnosis of higher order items taking up more space/time is the most correct one.

share|improve this answer
2  
For this answer please just use the direct comparison as the Help page suggests (shootout.alioth.debian.org/help.php#comparetwo) –  igouy May 15 '12 at 16:47
add comment
  • Scala performance is very decent if you just write Java/C-like code in Scala. The compiler will use JVM primitives for Int, Char, etc. when it can. While loops are just as efficient in Scala.
  • Keep in mind that lambda expressions are compiled to instances of anonymous subclasses of the Function classes. If you pass a lambda to map, the anonymous class needs to be instantiated (and some locals may need to be passed), and then every iteration has extra function call overhead (with some parameter passing) from the apply calls.
  • Many classes like scala.util.Random are just wrappers around equivalent JRE classes. The extra function call is slightly wasteful.
  • Watch out for implicits in performance-critical code. java.lang.Math.signum(x) is much more direct than x.signum(), which converts to RichInt and back.
  • Scala's main performance benefit over Java is specialization. Keep in mind that specialization is used sparingly in library code.
share|improve this answer
add comment
  • a) From my limited knowledge, I have to remark, that code in the static main method can't be optimized very good. You should move the critical code to a different location.
  • b) From long observations I would recommend not to do heavy output on performance test (except it is exactly what you like to optimize, but who should ever read 2 Million values?). You're measuring println, which isn't very interesting. Replacing the println with max:
(1 to 20000).toList.map (_ * 2).max

reduces the time from 800 ms to 20 on my system.

  • c) The for-comprehension is known to be a little slow (while we have to admit it's getting better all the time). Use while or tailrecursive functions instead. Not in this example, where it is the outer loop. Use the @tailrec-annotation, to test for tairecursiveness.
  • d) Comparing with C/Assembler fails. You don't rewrite scala code for different architectures for example. Other important difference to historic situations are
    • JIT-compiler, optimizing on the fly, and maybe dynamically, depending on input data
    • The importance of cache misses
    • The rising importance of parallel invocation. Scala today has solutions to work without much overhead in parallel. That's not possible in Java, except you do much more work.
share|improve this answer
2  
I have removed the println from the loop and actually the Scala code is faster than the Java code. –  Giorgio Jan 24 '12 at 22:27
    
The comparison with C and Assembler was meant in the following sense: a higher-level language has more powerful abstractions but you may need to use the lower-level language for performance. Does this parallel hold considering Scala as the higher-level and Java as the lower-level language? Maybe not, since Scala seems to deliver performance similar to Java. –  Giorgio Jan 24 '12 at 22:30
    
I wouldn't think it would matter much for Clojure or Scala but when I used to play around with jRuby and Jython I would have probably written the more performance critical code in Java. With those two I saw a significant disparity but that was years ago now...could be better. –  Rig Jan 25 '12 at 12:55
add comment

Check out my post a year of more ago on scala performance.

http://scala-forum.org/read.php?3,760,760#msg-760

I did a comparison of a common scala construct (using Range) and an iterative impl using a loop counter of types long and int. Got some interesting results. Also experimented with the scalacl plugin to optimise a bunch of the functional constructs.

Note you may note that my experiment is NOT actually testing scala performance but rather the performance of certain library classes such as Range.

Note also that microbenchmarks are always a bit tricky.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.