Project Lambda: Java Language Specification draft

Osvaldo Doederlein opinali at gmail.com
Thu Jan 28 14:14:49 PST 2010


2010/1/28 Reinier Zwitserloot <reinier at zwitserloot.com>

>  They designed [swing], apparently with the assumption that polymorphism,
>> stack frames, code size, extra indirection of some design patterns, etc. are
>> all "nickel-and-dime issues" that wouldn't matter.
>>
>
> You fantastically misunderstand the problems with the swing API. The
> complaints are about the _API_ - the way you build apps with it. Not about
> performance. Netbeans performs just fine and the API didn't change one whit.
> Yes, swing apps used to be slow. They fixed it, without removing any of the
> nickel and dime stuff. It would be annoying and complicated, from an API
> point of view, to state that list literals come in lots of varieties and
> have all these options. It would be far simpler if a list literal is always
> the same immutable structure, and if you need more/different features, you
> create a new list initialized with the list literal.
>

Swing performs well _now_, after a full decade of JVM&HW improvements. SWT
had near-native performance in 2001. And the current speed still comes with
a cost in size, loading time, JIT overheads. (I know this is not due only to
the factors I mention, but also to the lightweight-component architecture.
But those are important factors still.)


> Swing is actually an example of why your performance crusade is in fact
> wrong: It proves that high-level optimizations are the only ones that
> matter, and it also proves that making API simple and eliminate as many
> options and complications as possible is a good thing.
>

Unfortunately, most high-level optimizations are not possible in Swing -
these typically require structural changes, not possible in a white-box
framework that exposes too much of its internals as public APIs. So I bet
there was a ton of low-level opts instead - I'm not intimate with Swing's
sources, but I'm always reading sources of other JDK pieces and it is
SHOCK-FULL of "nickel-and-dime" opts, e.g. copying fields to local variables
to avoid repeated getfield's seems to be standard practice, as well as
manual hoisting of .length/.size() outside loops, etc. (I'm not claiming
that most of Swing's improvements came from such optimizations; the major
boost probably came from increased Java2D GPU acceleration. Once gain, just
not a great example.)


>  my NetBeans compiles pretty fast too, indeed both compilers are now
>> I/O-constrained on any recent machine/JVM, so this is not anymore a good
>> case study.
>>
>
> So, javac vs. ecj is no longer a good case study? Huh? No, it _IS_ a good
> case study, it is serious anecdotal avidence that that micro-optimization,
> which is what ecj has done, does not help performance any, and instead makes
> a dog of a code base that is such a drag on maintainability and flexiblity
> that eclipse is legendary for lagging behind new java features so much.
>

Here I won't dup Neal's reply.


> I'm still waiting on even one case study on your end that this micro
> optimization bullpuckey is worth screwing up language features for.
>

I never proposed that, I did explain my position but that's one of the parts
you chose to not reply.


> You, on the other hand, keeping saying, in elaborate overtures, "No, no,
>> they are important! Trust me, even though what I say goes against all common
>> knowledge and I have no proof or even a use case to back up what I say!".
>>
>
I can provide microbenchmarks that show the impact of low-level opts, but
you'd just shout back the cliché "microbenchmaks are worthless". So please
let me explain (again). I agree that low-level opts may only provide
extremely small gains (a few nanoseconds or bytes). But they DO make a
difference when your program does that thing A LOT. For example, pick any
Java program that is maths-bound and uses float values (e.g. a renderer),
and replace float->double. You'll notice an important big drop in
performance. A more concrete example: the compressed-oops optimization in
Sun's and IBM's recent JVMs, which basically saves 4 bytes per reference
field.

At best you can argue that we should leave low-level opts to the compiler,
not pollute our app code with that... but this is EXACTLY WHAT I WANT TO DO.
I want to use high-level language features like lambdas and collections,
without paying a price any higher than necessary. And I'm not proposing
major tradeoffs of functionality or syntax. (Very often, the major tradeoff
is extra effort in the language design, specification, and compiler
implementation.)


>  Yeah that would add yet special case to learn (if you care for precise
>> behavior), but the current spec is already counter-intuitive because Java
>> developers quickly learn that indexed iteration of ArrayList and friends is
>> better than using an Iterator (and won't ever throw CCE!), then comes
>> enhanced-for and breaks this intuition.
>>
>
> indexed iteration across an arraylist is better than using an iterator? I
> beg your pardon?
>
> Iterators don't HAVE to be fail-fast. There's extra logic in ArrayList and
> friends to make them fail-fast. someone back then (correctly, but a full
> discussion is beyond the scope of this thread) decided that fail-fast is
> worth it. If you want to turn this around and say that fail-fast is actively
> harmful compared to the standard 'who knows what's going to happen'
> behaviour of indexed access through an AL, that's your right, but you
> certainly can't do it by just saying that "It's better!" without backing
> this up!
>

If you desire fail-fast behavior, you can just use a standard for loop with
explicit Iterator. Now we can argue which priority should weight more -
performance or the protection of CCE. The enhanced-for supports primitive
arrays, and you can do a mess with a primitive array (cannot change its
structure, but can move elements around, including huge arraycopy
operations). Also, the fail-fast behavior has a very flexible/related spec
(check CCE's javadocs - there's a TON of caveats), and an implementation
that would simply ignore it everywhere would be just fine. In fact I would
gladly vote to make the fail-fast checks optional, guarded by JDK1.4
assertions so I could enable/disable them with -ea/-da; javac could also
avoid the enhanced-for optimization of RandomAccess collections with -g.
IT'S A FRIGGIN' DEBUGGING FEATURE. If treated as such, we could even make it
better with more extensive checking. (IBM once did such changes in their JDK
1.4.2 - and yeah it was great because it picked a bug in my app; OTOH it
sucked because the race was harmless and the CCE was screwing an app in
production inside a large bank. This impl change was uncompliant because the
CCE was being thrown by a method that doesn't document it as possible
behavior, so I reported this as a bug to the customer; IBM later removed
these changes.)

A+
Osvaldo



More information about the coin-dev mailing list