The Return of The Blob

I somehow managed to slow down my Scala program by a factor of 4 or so. A run that took less than an hour now takes over 3 hours. I ran with -Xprof profiling, and I see a lot of “ExceptionBlob”. What is that telling me, and what should I look for that could be causing it? I don’t throw/catch very many exceptions. What can be causing this inefficiency? Early returns?

Here is a small sample of the Xprof output:

 Compiled + native   Method                        

60.4% 160 + 0 ExceptionBlob
5.3% 13 + 1 scala.collection.immutable.NumericRange.foreach
5.3% 14 + 0 scala.collection.Iterator$GroupedIterator.deliver$1
4.2% 11 + 0 scala.collection.TraversableLike.map
3.8% 7 + 3 scala.collection.IterableLike$$Lambda$140.apply
2.6% 6 + 1 scala.collection.TraversableLike$WithFilter$$Lambda$291.apply
2.6% 7 + 0 scala.collection.immutable.VectorPointer.initFrom
2.3% 6 + 0 scala.collection.mutable.ArrayBuffer.foreach
1.5% 4 + 0 trajspec.InterpFunction$$Lambda$159.apply$mcDD$sp
0.8% 2 + 0 scala.collection.AbstractTraversable.max
0.8% 2 + 0 trajspec.InterpFunction$$$Lambda$165.apply
0.8% 2 + 0 trajspec.Route.$anonfun$position$2
0.8% 2 + 0 trajspec.InterpFunction.apply
0.8% 2 + 0 scala.collection.Iterator$GroupedIterator.go
0.4% 0 + 1 scala.collection.mutable.ListBuffer.$plus$eq
0.4% 1 + 0 scala.collection.AbstractIterator.foreach
0.4% 1 + 0 scala.collection.generic.GenericTraversableTemplate.genericBuilder$
0.4% 1 + 0 scala.collection.AbstractTraversable.genericBuilder
0.4% 1 + 0 scala.collection.IndexedSeqOptimized.isEmpty$
0.4% 1 + 0 scala.collection.TraversableOnce$$Lambda$98.apply
0.4% 1 + 0 trajspec.InterpFunction$$$Lambda$164.apply
0.4% 1 + 0 scala.collection.generic.Growable$$Lambda$5.apply
0.4% 1 + 0 scala.collection.IterableLike.foreach
0.4% 1 + 0 trajspec.InterpFunction.yvals
0.4% 1 + 0 scala.collection.TraversableLike.to
97.0% 250 + 7 Total compiled (including elided)

     Stub + native   Method                        

3.0% 0 + 8 java.lang.StrictMath.atan2
3.0% 0 + 8 Total stub

Thread-local ticks:
74.8% 788 Blocked (of total)

As you mention early returns, you already seem to know that they’re implemented as throwing an exception and catching it. If you use early returns in functions that are used often (e.g. in an iteration), this can well be the reason for the performance problems.

It should always be possible to refactor a function, so that it does not use early returns. Depending on how they are currently written and how many early returns they contain, this may result in deeply nested ifs, so you may have to split them.

Normal early returns will not use any exceptions. It’s only non-local returns (e.g. a return in a lambda function) that are implemented with exceptions. And still that mechanism uses a special Exception class which avoids constructing a stacktrace, which is the most expensive part of exception handling. I think in the worst case, the lambda function is not inlined and the JVM will have to unwind 1 stack frame (which I guess is what the ExceptionBlob is for). When you’re lucky either the scalac optimizer or the JIT will inline the lambda and the non-local return will amount to not much more than a goto statement with no stack unwinding required.
So… perhaps you have a non-inlined non-local return somewhere in a tight loop?

I figured out what the problem was, and it had nothing to do with the ExceptionBlob or early return statements. It was a data storage and accessing issue.