Hacker News new | ask | show | jobs
by hyperpape 3347 days ago
While I'm inclined to suspect that non-virtual by default is better from a design perspective‡, don't assume the point about performance is overwhelming. HotSpot has done devirtualization for a long time. You can detect not only when a method is never overridden, but also when it's never overridden at a particular call site. A virtual method that's never overridden can sometimes have no extra overhead, while a virtual method that is overridden may have sufficiently small overhead that it rarely matters.

http://insightfullogic.com/2014/May/12/fast-and-megamorphic-...

‡ I've used non-OO languages, but never an OO language without virtual by default.

3 comments

Since we're talking about performance: the time it takes HotSpot to perform this optimization is also a perf hit for your program.

At the end of the day, the fastest code is one that doesn't have to run.

HotSpot is an impressive technology but the optimizations it has to do to overcome Java's design really only pay for themselves in most frequently executed code paths and only after some time to gather necessary info to perform the optimizations.

It's ok for long-running server code but not good for, say, short-lived command-line program.

Or to put it differently: a language that has perf-friendly design, like Go, matches Java's speed with 10% of engineering time and resources spent on the compiler and optimizations. Perf friendly design means it has to do 10% of the work to achieve the same end result.

This may be true in general, but the CLR uses bytecode and a JIT compiler, so that point may be a lot less relevant to it. In addition, devirtualization is apparently valuable enough that they're going to add it to the CLR, per the article.
Java compiles to bytecode and most implementations JIT, just like .NET. JVMs are more advanced than the CLR at optimization.
Yes, my point is that once you're comparing two environments that use bytecode and a JIT, you can't necessarily cite the cost of startup time and the cost of JIT compilation as a reason to avoid possibly-virtual calls.
Depends. Recently I spent a day measuring every permutation of calculation-related optimizations I could think of for a critical inner code path. Then I noticed I'd lazily used one virtual call for convenience, which had been there since the prototype stage. The three minutes spent removing it was by far the biggest win that day.
It also just happens that the MS C# compiler always emits the `callvirt` instruction for instance methods, because the language spec requires that a NullReferenceException be thrown any time a method is called on a null instance, even if none of the instance fields are used in the method.

Source: https://blogs.msdn.microsoft.com/ericgu/2008/07/02/why-does-...