David Holmes wrote:
> Otherwise who determines that the code is indeed in need of rescue? Any why should you
> be trying to rescue it? Reasoning about these things (synchronization and
> performance), or even measuring them, is difficult enough without the
> compiler changing everything from underneath you.
>
> My concern is that the compiler is not necessarily smart enough to make a
> change that benefits the application as a whole when merging sync blocks -
> and that when that occurs it will be very difficult for the programmer to
> diagnose and correct. What is the motivating example for allowing the
> compiler to do this? What example of poor code occurs so frequently that
> having the compiler merge sync blocks is a winner for a majority of
> situations? Convince me that the benefits of the compiler getting it right
> will outweigh the costs of getting it wrong.
Maybe I'll answer your questions in reverse order, since the answer to the
last answers most of the rest. The answer is: we have different cost metrics
so what's right for "me" isn't nessecarily what's right for "you". Here "me"
is Sun & it's efforts to improve the Java experience for the bulk of it's users
(even if a few users have to suffer); part of that improvement effort is making
benchmarks run fast so, e.g. Microsoft, doesn't get the chance to splinter the
market based on performance. Here "you" is a competent programmer who
wishes to understand how the JVM & compiler work so you can write code
that will behave as expected, especially wrt optimization and synchronization.
A motivating example is find in the SciMark benchmark suite, which copped
a rather stock psuedo random number generator for use in a Monte Carlo
simulation. The generator is sync'd on reading and writing the internal state
so multi-threaded programs don't "reset" the generator back a few numbers or
blow the generator properties by mixing up the hidden state between numbers.
The generator is otherwise quite fast, which means the cost of sync'ing dominates;
since this is a Monte Carlo simulation, the program spends most of it's time
locking & unlocking the generator in a tight loop with very little work between
calls to the generator. It's all nice clean well abstracted code that was never
meant to be in an inner loop.
Another example, a little less extreme but WAY more common, is the current
state of the String libraries. Every other call and his mother locks something.
Even if we remove all the nested locks we find plenty of code where the user
writes "String::something; minor-niddling-thing; String::something_again".
Back-to-back string calls (and thus unlock/lock pairs) are quite common, with
maybe a counter or field update between the calls.
In both of these cases we can say "go rewrite the offending code!" but this
isn't feasible. Benchmarks have to stand on their own; rewriting them works
for V2.0 but not for generating performance numbers _today_. The libraries
_are_ being overhauled, but it's a long road and meantime there's a few million
copies of the existing libraries being used on a daily basis.
I think your concern is either overblown or misplaced. Compilers _can_ screw
liveness up, but compiler writers are in general a competent lot and we are well
aware of what screwing up liveness will do. After all, Sun's bread-and-butter is
large multi-headed servers running many-threaded apps. In general, we'll only
be fusing when we can show that the amount of work captured into the lock is
boundedly small.
Let me reverse your question and ask you for an example where a compiler might
try to fuse locks and accidently blow liveness. We'll start by ruling out all calls in
the inbetween area; if the compiler can't inline the call away all bets are off. Also,
nix on unbounded loops or loops where we can't determine the trip count is short.
(Long counted loops can be unrolled-and-jam'd; this allows us to reduce sync
costs to an arbitrary fraction while keeping the lock-held time low).
Cliff
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:30 EDT