Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #36530 > unrolled thread
| Started by | Marcel Mueller <news.5.maazl@spamgourmet.org> |
|---|---|
| First post | 2017-04-25 22:07 +0200 |
| Last post | 2017-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.
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
| From | Marcel Mueller <news.5.maazl@spamgourmet.org> |
|---|---|
| Date | 2017-04-25 22:07 +0200 |
| Subject | Re: 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]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2017-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]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2017-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]
| From | Marcel Mueller <news.5.maazl@spamgourmet.org> |
|---|---|
| Date | 2017-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]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2017-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]
| From | Arne Vajhøj <arne@vajhoej.dk> |
|---|---|
| Date | 2017-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