Writing Performant Scala(sumologic.com)
sumologic.com
Writing Performant Scala
http://www.sumologic.com/blog/technology/3-tips-for-writing-performant-scala
6 comments
Keep in mind that the while loop is 3x faster because the loop itself is doing a trivial amount of work. As your loops get larger, call functions that do more work, or operate on objects instead of primitives, the overhead of using idiomatic Scala drops considerably.
Another important point: the idiomatic Scala version is one concise, purely functional line. The second version on the other hand is 6 lines and involves mutation. If you were to embed it in another part of the program in a purely functional way, you'd have to wrap it in curly braces and add an extra expression to return the final value of x, upping it to 9 lines. Claim what you want about readability, but lines of code impose a cognitive burden, both in reading them and scrolling through them. I'd much rather express an idea in one line of pure code if possible than with 6-9 lines of code that modifies state.
Another important point: the idiomatic Scala version is one concise, purely functional line. The second version on the other hand is 6 lines and involves mutation. If you were to embed it in another part of the program in a purely functional way, you'd have to wrap it in curly braces and add an extra expression to return the final value of x, upping it to 9 lines. Claim what you want about readability, but lines of code impose a cognitive burden, both in reading them and scrolling through them. I'd much rather express an idea in one line of pure code if possible than with 6-9 lines of code that modifies state.
In real production code, things like this are rarely bottlenecks. The count version, frankly, is less error prone. There are a few different ways that you can easily mess up the while loop version. In places where a loop like this really is the bottleneck we'll drop in the C-style version.
In general though, we find the code just kind of balloons if you use patterns like this everywhere.
In general though, we find the code just kind of balloons if you use patterns like this everywhere.
I have to agree with mrdmnd here.
I know the old saying about premature optimization, but avoiding premature optimization doesn't mean actively choosing slower code. It just seems like sloppy programming, IMO.
I know the old saying about premature optimization, but avoiding premature optimization doesn't mean actively choosing slower code. It just seems like sloppy programming, IMO.
Concise, readable code should trump performance concerns in cases where performance doesn't matter. The idiomatic version is much shorter and clearer.
The equating of writing slower code to "sloppy programming" seems like sloppy reasoning to me. If it was sloppy to knowingly go with a slower solution, then using Python, for instance, or any scripting language for that matter, would always be "sloppy".
It isn't.
For me, Scala provides a happy middle ground between a scripting language like Python, and an "enterprise" language like Java. Scala is as nearly performant as Java--and sometimes it performs significantly better than Java due to having parallel collections, and the like--while having nearly the expressiveness of a scripting language like Python.
Also, Scala's performance issues are overblown. I program in Scala professionally every day and it performs great.
It isn't.
For me, Scala provides a happy middle ground between a scripting language like Python, and an "enterprise" language like Java. Scala is as nearly performant as Java--and sometimes it performs significantly better than Java due to having parallel collections, and the like--while having nearly the expressiveness of a scripting language like Python.
Also, Scala's performance issues are overblown. I program in Scala professionally every day and it performs great.
Its does annoy me that lazy evaluation is not the default like it is in Haskell for much of the collections classes, but Once you figure out its there, man does it make things faster.
The fact that it takes so much intimate knowledge of how the collections are implemented to get some decent performances in Scala is probably one of the many reasons why this language hasn't taken off.
I agree in principle that one shouldn't have to understand the implementation of collections to use them effectively, but these limitations are by no means exclusive to Scala. Haskell's lists, difference lists and seqs work exactly the same way as Scala's list collections. Iteratively concatenating strings in Python will murder your performance. Most (all?) sufficiently complex systems involve tradeoffs.
> Iteratively concatenating strings in Python will murder your performance.
Understanding immutable strings aren't at the same level. People concatenate immutable strings all the time in Java/Python, but that is despite the documentation mentioning immutability and proper concatenation method(StringBuffer followed by toString, list.append() followed by " ".join(list))
Understanding immutable strings aren't at the same level. People concatenate immutable strings all the time in Java/Python, but that is despite the documentation mentioning immutability and proper concatenation method(StringBuffer followed by toString, list.append() followed by " ".join(list))
> despite the documentation mentioning immutability and proper concatenation method
What-do-you-know, Scala has documentation too[1]! And it mentions that appending to a List is O(n).
[1] http://www.scala-lang.org/api/current/scala/collection/immut...
What-do-you-know, Scala has documentation too[1]! And it mentions that appending to a List is O(n).
[1] http://www.scala-lang.org/api/current/scala/collection/immut...
I'm not sure what you mean by "hasn't taken off". Scala is pretty thriving in these parts: I.e., we use Scala where I work. Headhunters contact me about open Scala positions. A few months back there was a Scala symposium down the street that had several hundred attendees. There is a local user group that is "sold out every month. I.e., the room holds 75 people, and more than that number always wants to attend. Etc.
It takes a long time for a new general purpose programming language to displace existing general purpose programming languages if it doesn't fill a very particular niche for which there is a great demand.
Re performance, I recently implemented an algorithm in Scala that performs quite well. It didn't at first, but it was very easy for me to profile it using Java profiling tools and to tighten a couple of loops where most of the CPU was being consumed. I don't have any deep knowledge of Scala collections, but I know how to use a profiler. I don't think the initial implementation would have performed any better if it had been written in Java.
Once I had gotten things speedy enough, I was further able to speed everything up by 4X just by changing a collection to the parallel version of the collection. Then all four cores could crunch on it. If I had 8 cores, it would have no doubt run 8X faster. That parallelization came from tweaking only one line of code! I would have never achieved this 4X speedup in Java.
It takes a long time for a new general purpose programming language to displace existing general purpose programming languages if it doesn't fill a very particular niche for which there is a great demand.
Re performance, I recently implemented an algorithm in Scala that performs quite well. It didn't at first, but it was very easy for me to profile it using Java profiling tools and to tighten a couple of loops where most of the CPU was being consumed. I don't have any deep knowledge of Scala collections, but I know how to use a profiler. I don't think the initial implementation would have performed any better if it had been written in Java.
Once I had gotten things speedy enough, I was further able to speed everything up by 4X just by changing a collection to the parallel version of the collection. Then all four cores could crunch on it. If I had 8 cores, it would have no doubt run 8X faster. That parallelization came from tweaking only one line of code! I would have never achieved this 4X speedup in Java.
Data structures have inherent time and space complexity tradeoffs. This is just as true in C as it is in Scala.
Remember folks : "performant" is not a word.
http://boulter.com/blog/2004/08/19/performant-is-not-a-word/
http://boulter.com/blog/2004/08/19/performant-is-not-a-word/
"performant" may become legitimate soon, but it seems destined to be another tech buzz/weasel word.
Thanks for pointing that out Don.
So basically the recommendations boil down to "pretend youre using Haskell a work" :-)
Also, hi Russell!