Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #36530 > unrolled thread

Re: Generics and downcasts

Started byMarcel Mueller <news.5.maazl@spamgourmet.org>
First post2017-04-25 22:07 +0200
Last post2017-04-25 19:53 -0400
Articles 7 — 4 participants

Back to article view | Back to comp.lang.java.programmer

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Generics and downcasts Marcel Mueller <news.5.maazl@spamgourmet.org> - 2017-04-25 22:07 +0200
    Re: Generics and downcasts Arne Vajhøj <arne@vajhoej.dk> - 2017-04-25 16:20 -0400
      Re: Generics and downcasts Eric Douglas <e.d.programmer@gmail.com> - 2017-04-25 13:35 -0700
        Re: Generics and downcasts Arne Vajhøj <arne@vajhoej.dk> - 2017-04-25 19:54 -0400
      Re: Generics and downcasts Marcel Mueller <news.5.maazl@spamgourmet.org> - 2017-04-25 22:40 +0200
        Re: Generics and downcasts Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-04-25 18:13 -0400
        Re: Generics and downcasts Arne Vajhøj <arne@vajhoej.dk> - 2017-04-25 19:53 -0400

#36530 — Re: Generics and downcasts

FromMarcel Mueller <news.5.maazl@spamgourmet.org>
Date2017-04-25 22:07 +0200
SubjectRe: Generics and downcasts
Message-ID<odoaaj$9q$1@gwaiyur.mb-net.net>
On 25.04.17 00.23, Stefan Ram wrote:
> Cast-iron guarantee: the implicit casts added by the
> compilation of generics never fail.
>
>    This, of course, immediatly leads to the question:
>
>    Since the downcasts added during the compilation of
>    the above generic code can never fail and since they
>    add run-time costs, can't they be omitted?

It depends on your definition of "omitted".

Technically at machine instruction level cast expression are not 
required at all. Everything is an object at this level, no more no less.

But to get meaningful exceptions instead of undefined behavior and JVM 
crashes cast expressions evaluate to type checks. I.e
   x = (sometype)y;
is basically the same than
   if (!(a instanceof sometype))
     throw new ClassCastException(...);
   x = y;
except that the latter does not compile because of compiler 
restrictions. So a cast expression does not generate much executable 
code. It is just a conditional expression that is typically false.

>    Maybe the purpose of these downcasts is to add
>    additional safety for the case of some parts of a
>    program not using generics. (I.e., in the presence of
>    "unchecked" warning.)

Yes, this is an important issue.

>    A program might define a /private/ generic class and make
>    sure that /all/ accesses to this class use generics, yet it
>    still has to pay the price of those downcasts!

It has to pay for the concept of type erasure with compatibility to old 
code.

If you dislike that, choose another language. .NET for instance has 
strong typing at IL level and does not share this impact. (If you anyhow 
manage to get a wrong object type in your container you get really funny 
runtime exceptions.)
The presence of structured value types in .NET add further performance 
improvements if used well.

If this still does not fit to your needs use C++. This can generate code 
similarly efficient than machine code with almost all checks done at 
compile time.
But even in C++ type erasure is a very efficient concept. The bad news 
is that have have to do it yourself by using a non template base class. 
The latter does the work and the strongly typed subclass just adds type 
safety but does not generate any executable code.

But in practice these differences are not relevant in most use cases.

There are other pitfalls that are by far more expensive.
E.g. if you miss to declare a trivial Java method as final. This 
prevents the JIT from inlining the method body. This may add an overhead 
of an order of magnitude or even more. In C++ getter or delegation 
methods may not generate even one machine instruction. In managed 
languages like Java there is always a small overhead if you want the 
stack trace of exceptions to be reliable. But this is by far less than a 
virtual method call.
And even this is negligible compared to an additional invocation of the 
new operator.

Basically type erasure reduces the working set size of your code. This 
can improve cache efficiency which may be more relevant than the impact 
by type checks.

If you worry about performance have a look at you algorithms and data 
structures first. Only if you can't squeeze out more performance at this 
level dig down to lower levels. From my experience optimizing algorithms 
and data structures often has a gain of orders of magnitudes while doing 
optimizations at code level only adds a small factor.


Marcel

[toc] | [next] | [standalone]


#36531

FromArne Vajhøj <arne@vajhoej.dk>
Date2017-04-25 16:20 -0400
Message-ID<odob39$s00$1@gioia.aioe.org>
In reply to#36530
On 4/25/2017 4:07 PM, Marcel Mueller wrote:
[bunch of good stuff deleted]
> It has to pay for the concept of type erasure with compatibility to old
> code.
>
> If you dislike that, choose another language. .NET for instance has
> strong typing at IL level and does not share this impact.

.NET got generics relative early in its history, so MS decided
that compatibility with old collection classes was not that important.
Java was in a different situation, so type erasure and collection
compatibility was chosen. And we have to live with it.

> There are other pitfalls that are by far more expensive.
> E.g. if you miss to declare a trivial Java method as final. This
> prevents the JIT from inlining the method body. This may add an overhead
> of an order of magnitude or even more.

I think this is a myth.

https://www.ibm.com/developerworks/library/j-jtp1029/  (Brian Goetz 2002)

<quote>
Like many myths about Java performance, the erroneous belief that 
declaring classes or methods as final results in better performance is 
widely held but rarely examined. The argument goes that declaring a 
method or class as final means that the compiler can inline method calls 
more aggressively, because it knows that at run time this is definitely 
the version of the method that's going to be called. But this is simply 
not true. Just because class X is compiled against final class Y doesn't 
mean that the same version of class Y will be loaded at run time. So the 
compiler cannot inline such cross-class method calls safely, final or 
not. Only if a method is private can the compiler inline it freely, and 
in that case, the final keyword would be redundant.
</quote>

Arne

[toc] | [prev] | [next] | [standalone]


#36532

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-04-25 13:35 -0700
Message-ID<90e70a8b-5e6d-45cc-a42d-976b2dec543e@googlegroups.com>
In reply to#36531
On Tuesday, April 25, 2017 at 4:21:08 PM UTC-4, Arne Vajhøj wrote:
> <quote>
> Like many myths about Java performance, the erroneous belief that 
> declaring classes or methods as final results in better performance is 
> widely held but rarely examined. The argument goes that declaring a 
> method or class as final means that the compiler can inline method calls 
> more aggressively, because it knows that at run time this is definitely 
> the version of the method that's going to be called. But this is simply 
> not true. Just because class X is compiled against final class Y doesn't 
> mean that the same version of class Y will be loaded at run time. So the 
> compiler cannot inline such cross-class method calls safely, final or 
> not. Only if a method is private can the compiler inline it freely, and 
> in that case, the final keyword would be redundant.
> </quote>
> 
> Arne

Eclipse Cleanup adds final modifiers all over the place.  I don't recall if these are supposed to help performance.  All I know is 3 of the purposes for final.  1) declaring a public, usually static constant variable 2) declaring a class that should never be extended and 3) declaring a variable in a class that needs to pass directly into something, like a SwingWorker.

[toc] | [prev] | [next] | [standalone]


#36536

FromArne Vajhøj <arne@vajhoej.dk>
Date2017-04-25 19:54 -0400
Message-ID<odonjn$1h56$2@gioia.aioe.org>
In reply to#36532
On 4/25/2017 4:35 PM, Eric Douglas wrote:
> On Tuesday, April 25, 2017 at 4:21:08 PM UTC-4, Arne Vajhøj wrote:
>> <quote> Like many myths about Java performance, the erroneous
>> belief that declaring classes or methods as final results in better
>> performance is widely held but rarely examined. The argument goes
>> that declaring a method or class as final means that the compiler
>> can inline method calls more aggressively, because it knows that at
>> run time this is definitely the version of the method that's going
>> to be called. But this is simply not true. Just because class X is
>> compiled against final class Y doesn't mean that the same version
>> of class Y will be loaded at run time. So the compiler cannot
>> inline such cross-class method calls safely, final or not. Only if
>> a method is private can the compiler inline it freely, and in that
>> case, the final keyword would be redundant. </quote>
>
> Eclipse Cleanup adds final modifiers all over the place.  I don't
> recall if these are supposed to help performance.  All I know is 3 of
> the purposes for final.  1) declaring a public, usually static
> constant variable 2) declaring a class that should never be extended
> and 3) declaring a variable in a class that needs to pass directly
> into something, like a SwingWorker.

There are reasons to use final. Just not performance optimization.

Arne

[toc] | [prev] | [next] | [standalone]


#36533

FromMarcel Mueller <news.5.maazl@spamgourmet.org>
Date2017-04-25 22:40 +0200
Message-ID<odoc85$5b4$1@gwaiyur.mb-net.net>
In reply to#36531
On 25.04.17 22.20, Arne Vajhøj wrote:
> .NET got generics relative early in its history, so MS decided
> that compatibility with old collection classes was not that important.
> Java was in a different situation, so type erasure and collection
> compatibility was chosen. And we have to live with it.

The bad news is that although this breaking change they did not manage 
to give their new container classes a consistent interface. There are at 
least 4 distinct and fully equivalent implementation of the Count 
property. And methods with the same name (like Add) have significantly 
different semantics in different container types.

>> There are other pitfalls that are by far more expensive.
>> E.g. if you miss to declare a trivial Java method as final. This
>> prevents the JIT from inlining the method body. This may add an overhead
>> of an order of magnitude or even more.
>
> I think this is a myth.
>
> https://www.ibm.com/developerworks/library/j-jtp1029/  (Brian Goetz 2002)
>
> <quote>
> Like many myths about Java performance, the erroneous belief that
> declaring classes or methods as final results in better performance is
> widely held but rarely examined. The argument goes that declaring a
> method or class as final means that the compiler can inline method calls
> more aggressively, because it knows that at run time this is definitely
> the version of the method that's going to be called. But this is simply
> not true. Just because class X is compiled against final class Y doesn't
> mean that the same version of class Y will be loaded at run time. So the
> compiler cannot inline such cross-class method calls safely, final or
> not. Only if a method is private can the compiler inline it freely, and
> in that case, the final keyword would be redundant.
> </quote>

I never said that the Java compiler might inline such function calls. 
This is up to the JIT.


Marcel

[toc] | [prev] | [next] | [standalone]


#36534

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2017-04-25 18:13 -0400
Message-ID<odohfm$i47$1@dont-email.me>
In reply to#36533
On 4/25/2017 4:40 PM, Marcel Mueller wrote:
> On 25.04.17 22.20, Arne Vajhøj wrote:
>> [Marcel Mueller also wrote; attribution lost:]
>>> There are other pitfalls that are by far more expensive.
>>> E.g. if you miss to declare a trivial Java method as final. This
>>> prevents the JIT from inlining the method body. This may add an overhead
>>> of an order of magnitude or even more.
>>
>> I think this is a myth.
>>
>> https://www.ibm.com/developerworks/library/j-jtp1029/  (Brian Goetz 2002)
>> [...]
> 
> I never said that the Java compiler might inline such function calls. 
> This is up to the JIT.

     The JIT is able to inline non-final and non-private methods.  Here's
a page with some information on how you can watch it happening:

https://techblug.wordpress.com/2013/08/19/java-jit-compiler-inlining/

-- 
esosman@comcast-dot-net.invalid
Thirteen hundred sixty-six days to go.

[toc] | [prev] | [next] | [standalone]


#36535

FromArne Vajhøj <arne@vajhoej.dk>
Date2017-04-25 19:53 -0400
Message-ID<odonh5$1h56$1@gioia.aioe.org>
In reply to#36533
On 4/25/2017 4:40 PM, Marcel Mueller wrote:
> On 25.04.17 22.20, Arne Vajhøj wrote:
>> .NET got generics relative early in its history, so MS decided
>> that compatibility with old collection classes was not that important.
>> Java was in a different situation, so type erasure and collection
>> compatibility was chosen. And we have to live with it.
>
> The bad news is that although this breaking change they did not manage
> to give their new container classes a consistent interface. There are at
> least 4 distinct and fully equivalent implementation of the Count
> property. And methods with the same name (like Add) have significantly
> different semantics in different container types.
>
>>> There are other pitfalls that are by far more expensive.
>>> E.g. if you miss to declare a trivial Java method as final. This
>>> prevents the JIT from inlining the method body. This may add an overhead
>>> of an order of magnitude or even more.
>>
>> I think this is a myth.
>>
>> https://www.ibm.com/developerworks/library/j-jtp1029/  (Brian Goetz 2002)
>>
>> <quote>
>> Like many myths about Java performance, the erroneous belief that
>> declaring classes or methods as final results in better performance is
>> widely held but rarely examined. The argument goes that declaring a
>> method or class as final means that the compiler can inline method calls
>> more aggressively, because it knows that at run time this is definitely
>> the version of the method that's going to be called. But this is simply
>> not true. Just because class X is compiled against final class Y doesn't
>> mean that the same version of class Y will be loaded at run time. So the
>> compiler cannot inline such cross-class method calls safely, final or
>> not. Only if a method is private can the compiler inline it freely, and
>> in that case, the final keyword would be redundant.
>> </quote>
>
> I never said that the Java compiler might inline such function calls.
> This is up to the JIT.

Well - next section covers that more explicit.

<quote>
On the other hand, the run-time environment and JIT compiler have more 
information about what classes are actually loaded, and can make much 
better optimization decisions than the compiler can. If the run-time 
environment knows that no classes are loaded that extend Y, then it can 
safely inline calls to methods of Y, regardless of whether Y is final 
(as long as it can invalidate such JIT-compiled code if a subclass of Y 
is later loaded). So the reality is that while final might be a useful 
hint to a dumb run-time optimizer that doesn't perform any global 
dependency analysis, its use doesn't actually enable very many 
compile-time optimizations, and is not needed by a smart JIT to perform 
run-time optimizations.
</quote>

Arne


[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web