Yesterday, I started playing around with JRockit's MissionControl tool, now that we run on JRockit.
One of the (quite surprising) findings was that we generated over 1.3 million ClassNotFoundExceptions during the compilation of Maxima. With two simple changes nearly all of those have been removed.
There are still quite a few exceptions associated with our loading process though, as our ZipCache seems to trigger integer parsing exceptions in URLs internally; from the names of the functions through which the exceptions are being found, it looks like Java wants to parse IPv4-dot-separated tuples as host names. Our URLs don't have hostnames most of the time: we're passing file:// URLs!
Running an exception profile on Maxima running its test suite shows lots of non-local transfer of control exceptions: Return, Go and Throw: during a run of ca 10 minutes, I'm finding 5.5 million exceptions being thrown which - as MissionControl calculated for me - should mean an average of little over 12k/s. I guess that's kind of expected with our strategy for non-local transfers of control. However, if rethrows are counted as well, we can probably do better: by minimizing the number of try/catch blocks in our compiled code which reset special bindings.
To illustrate what I mean, the example
""" (declaim (special *x*)) (defun foo (*X*) (let ((*X* 1)) (let ((*X* 2)) 0))) """
Decompiles into (pseudo code):
foo(*X*): function_setup_code reg1 = current_specials_state() try { bind_special(*X*, arg1) reg2 = current_specials_state() try { bind_special(*X*, 1) reg3 = current_specials_state() try { bind_special(*X*, 2) reg4 = integer_0 } catch (Throwable t) { reset_specials_state(reg3) rethrow t } reset_specials_state(reg3) } catch (Throwable t) { reset_specials_state(reg2) rethrow t } reset_specials_state(reg2) } catch (Throwable t) { reset_specials_state(reg1) rethrow t } reset_specials_state(reg1) return reg4
As you see, to handle a single non-local transfer of control, we throw and catch the same exception 3 times. This issue is known as ticket #90 (http://trac.common-lisp.net/armedbear/ticket/90).
It would be really nice to hash through all the different situations which may need special-bindings-state to be reset with a few of you and resetting *only* those cases. I'm hoping our general performance - and the Maxima-on-ABCL performance because of its many special variables in particular. BTW: ABCL came from the situation where it tried to use that scheme, but the way it was implemented made it really hard to find out where specials were leaking - and they were.
Bye,
Erik.
On Sat, Nov 6, 2010 at 7:24 PM, Erik Huelsmann ehuels@gmail.com wrote:
Yesterday, I started playing around with JRockit's MissionControl tool, now that we run on JRockit.
Running an exception profile on Maxima running its test suite shows lots of non-local transfer of control exceptions: Return, Go and Throw: during a run of ca 10 minutes, I'm finding 5.5 million exceptions being thrown which - as MissionControl calculated for me - should mean an average of little over 12k/s. I guess that's kind of expected with our strategy for non-local transfers of control.
To put this into context we (developers at JRockit) expect ~1000 exceptions / core / sec from a "typical" Weblogic app. We define this as a bit much but not terribly excessive.
My guess is that between the horrible support for fixnums (and the really slow bignums) in Java and the order of magnitude higher exception count this will dominate your performance.
cheers /J
Hi Joel,
Running an exception profile on Maxima running its test suite shows lots of non-local transfer of control exceptions: Return, Go and Throw: during a run of ca 10 minutes, I'm finding 5.5 million exceptions being thrown which - as MissionControl calculated for me - should mean an average of little over 12k/s. I guess that's kind of expected with our strategy for non-local transfers of control.
To put this into context we (developers at JRockit) expect ~1000 exceptions / core / sec from a "typical" Weblogic app. We define this as a bit much but not terribly excessive.
My guess is that between the horrible support for fixnums (and the really slow bignums) in Java and the order of magnitude higher exception count this will dominate your performance.
Does the exception count include all "rethrow"s which are part of the "finally" processing? If all "athrow" instructions are being counted, I think we can do better, if we think this through really well.
Regards,
Erik.
Hi Joel,
On Tue, Nov 9, 2010 at 11:00 AM, Erik Huelsmann ehuels@gmail.com wrote:
Hi Joel,
Running an exception profile on Maxima running its test suite shows lots of non-local transfer of control exceptions: Return, Go and Throw: during a run of ca 10 minutes, I'm finding 5.5 million exceptions being thrown which - as MissionControl calculated for me - should mean an average of little over 12k/s. I guess that's kind of expected with our strategy for non-local transfers of control.
To put this into context we (developers at JRockit) expect ~1000 exceptions / core / sec from a "typical" Weblogic app. We define this as a bit much but not terribly excessive.
My guess is that between the horrible support for fixnums (and the really slow bignums) in Java and the order of magnitude higher exception count this will dominate your performance.
Trying to find out how much it matters, I changed ABCL's compiler according to my ideas in the mail I stated earlier today. It seems MissionControl indeed measures the number of 'athrow' opcodes executed. Reducing the number of try/catch blocks (and hence the number of rethrows) by 60% [measured during the first 3 minutes of Maxima's test suite], I was able to reduce the total Maxima test suite evaluation time by a whopping 2% :-)
One of the explanations I can come up with is that our ControlTransfer exceptions don't snapshot the stack: we've disabled stack snapshotting on them because we found the impact of stack snapshots to be huge. In our case, ControlTransfer is just an exceptional situation, not an error, so, we're 99,999999999% of the time not interested in the stacktrace it comes with.
I do think however that code resulting from the design that I wrote down is much cleaner in terms of number of exception blocks etc. So, I might commit it anyway. I'll still need to clean up the interpreter part of things though.
Do you have some further ideas for profiling ABCL, possibly with Maxima?
Bye,
Erik.
armedbear-devel@common-lisp.net