News for hackers. Stuff that matters.
Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by chrisseaton on Monday December 18, 2017 @04:59PM (#15955900)
> I heard so many times that JVM is much better than CLR, especially in the JIT area (Hotspot?).

I wouldn't disagree with this (I work at Oracle on VM research), but I've been told by other people that Microsoft or at least the .NET just generally prefer a simpler approach, without profiling, dynamic compilation, deoptimisation, and other complexity the approach used by the JVM brings. It's much more what-you-see-is-what-you-get from their JIT, rather than the mind-binding things the JVM manages to do with some code, and maybe that makes life easier for their use cases.

I'm not sure they want to add the same kind of complexity that the JVM has, even if it did bring them some better performance. But as I say that's second hand conversations.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by _ivvf on Monday December 18, 2017 @05:28PM (#15956085)
I definitely agree with this stance, and would say that languages like C# and golang have a weaker runtime but try to make up for it in other ways, often surpassing Java in certain areas. For instance, both languages have stack-allocated types to help stress the GC less. C# also has a much better native interop story than Java, as well as the unsafe keyword.

At the end of the day, if you want amazing performance in Java, you have to write C-like code in Java, and that often involves things like managing your own offheap memory, sticking with arrays of numbers, etc. Java's biggest areas for improvement in the performance arena are going to come allowing for stack-allocated types, fully-continugous arrays, less overhead when calling native code, and providing official APIs for the other things you can currently do with sun.misc.Unsafe.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by naasking on Monday December 18, 2017 @07:33PM (#15956793)
The .NET runtime is weaker on the JIT side, but the lack of type erasure on generics is very complicated all on it's own. Java doesn't have to deal with this. In fact, .NET is the only VM I know of with this feature.

Fortunately, it permits a lot of interesting manual optimizations you can't easily express when runtime types aren't available.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by seanmcdirmid on Monday December 18, 2017 @08:45PM (#15957113)
The lack of erasure is a huge usability win (types don’t disappear at run time), as well as a performance win (I’ve been able to do great things with C# generics + value types). I also like the way it naturally deals with static fields (useful for factory routines).
Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by pron on Tuesday December 19, 2017 @05:21AM (#15959168)
I think it's a huge loss. Generic type erasure is the main thing that makes simple polyglot interop and code-reuse on the JVM possible. Even things like Python become clunky on .NET because of runtime generics. I gladly give up on the tiny usability gain in exchange for having a rich language ecosystem.

Value types are a different matter, and they are now being added to Java as well. Specialized generics over value types are different from specialized generics for reference types, because they are always invariant.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by throwaway010317 on Tuesday December 19, 2017 @04:17AM (#15958872)
I use C# in my day job and try to learn as much as I can about cool ways to use its type system. Genuinely curious to see some examples if you're able to point me in the right direction?

> I’ve been able to do great things with C# generics + value types

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by naasking on Tuesday December 19, 2017 @10:16AM (#15960736)
You can see a few tricks in my project here: https://github.com/naasking/Dynamics.NET

You can use static classes to cache information about types. That project caches delegates to perform deep copies, to invoke constructors, to check for deep immutability, and whether a type can contain any cycles. This is all done structurally via reflection, but the results are executed only once and cached in static fields by exploiting runtime types.

The cached delegate trick can be used whenever you need to some efficient dynamic dispatching. I use it here [1] in another project to cache the Dapper methods that would be invoked so I can easily compose smaller queries into larger ones that return very complicated objects.

A more complicated example would be the fastest immutable dictionary available for .NET in my Sasa library [2]. Generic methods and types defined on structs are JITted separately, so the dispatching overhead is low. I exploit this to create a very efficient hash array mapped trie.

[1] https://github.com/naasking/Dapper.Compose/blob/master/Dappe...

[2] https://sourceforge.net/p/sasa/code/ci/default/tree/Sasa.Col...

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by matthewwarren on Monday December 18, 2017 @05:30PM (#15956095)
> but I've been told by other people that Microsoft or at least the .NET just generally prefer a simpler approach, without profiling, dynamic compilation, deoptimisation, and other complexity the approach used by the JVM brings. It's much more what-you-see-is-what-you-get from their JIT, rather than the mind-binding things the JVM manages to do with some code, and maybe that makes life easier for their use cases.

Interesting, it's clear after a bit of research that this is the case (i.e. .NET JIT simpler that Hotspot), but it had never occurred to me that it was a conscious decision

I'd always thought that the .NET was just playing catch-up and/or didn't need to do all the things that Hotspot does. (for instance .NET has value types or 'stucts' so some optimisations are not needed because the programmer can just use them instead of classes, if they need the perf boost)

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by sillypuddy on Monday December 18, 2017 @06:06PM (#15956297)
It has been a deliberate decision. The Book of the Runtime documentation states "The goal of the CLR is to make programming easy" and acknowledges there are faster alternatives out there. When I have asked insiders why there isn't a bigger focus on performance, the response is essentially that if performance is really important you should use C++.
Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by pjmlp on Tuesday December 19, 2017 @02:26AM (#15958405)
That point of view is outdated.

Hence Roslyn, .NET Native with VC++ backend, value types improvements and safer pointers in 7.x.

There are even plans to slowly move parts of the runtime from C++ into C#, now that .NET Native is a thing.

" So, in my view, the primary trend is moving our existing C++ codebase to C#. It makes us so much more efficient and enables a broader set of .NET developers to reason about the base platform more easily and also contribute"

https://www.infoq.com/articles/virtual-panel-dotnet-future

https://www.infoq.com/articles/high-performance-dotnet

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by readittwice on Tuesday December 19, 2017 @05:37AM (#15959238)
Java seems to have a similar initiative called "Project Metropolis" to (re)write some stuff in Java instead of C++: http://mail.openjdk.java.net/pipermail/discuss/2017-Septembe...
Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by matthewwarren on Monday December 18, 2017 @06:59PM (#15956636)
> The Book of the Runtime documentation states "The goal of the CLR is to make programming easy"

In case anyone else is interested, that quote comes from https://github.com/dotnet/coreclr/blob/master/Documentation/...

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by benaadams on Monday December 18, 2017 @08:23PM (#15957033)
Also says

> The .NET runtime supports a wide variety of high performance applications. As such, performance is a key design element for every change.

https://github.com/dotnet/coreclr/blob/master/Documentation/...

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by mehrdadn on Monday December 18, 2017 @06:05PM (#15956292)
>> I heard so many times that JVM is much better than CLR, especially in the JIT area (Hotspot?).

> I wouldn't disagree with this

I would wholeheartedly disagree with this though. There's not even any way to write, say, a generic class (even one as simple as ArrayList<T>) and then let the user instantiate it with a primitive type like <int> in Java. To use generics in Java is to pay the speed penalty of an indirection for every single primitive type on top of the extra per-object bytes of space overhead. There's just no way Java is going to fix these problems without massive breaking changes in the type system or an extremely in-depth & expensive form of static analysis unlike anything I've seen in any real-world compiler.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by chrisseaton on Monday December 18, 2017 @06:18PM (#15956344)
You're not disagreeing with me, because we're talking about different things!

You're talking about Java, the language, I'm talking about the JVM, really HotSpot, really C2 actually, the implementation and the techniques it uses, whatever the language is, compared to the techniques that the .NET CLR uses.

The points you bring up are interesting though, because some of these complexities (which HotSpot isn't responsible for or in a position to change!) are as someone else has said, probably partly what has motivated the extra work in C2 compared to the .NET CLR JIT.

> To use generics in Java is to pay the speed penalty of an indirection for every single element on top of the extra per-object bytes of space overhead.

And this is just false - the extra indirection only applies for elements that are boxed primitives, not 'every single element'. There is no extra indirection for things that are references anyway.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by mehrdadn on Monday December 18, 2017 @06:56PM (#15956613)
> You're not disagreeing with me, because we're talking about different things! You're talking about Java, the language, I'm talking about the JVM, really HotSpot, really C2 actually, the implementation and the techniques it uses, whatever the language is, compared to the techniques that the .NET CLR uses.

No, we are disagreeing. I'm talking about how repercussions of decisions in the language affect the implementation. My comment was not at all limited to just the language itself. If you read my comment, you notice I mentioned fixing these issues would require changes in either the type system or an "expensive form of static analysis unlike anything I've seen in any real-world compiler". Because when the language dictates that there must be an indirection, the implementation can only remove it when it can prove that doing so would be transparent to the code, which is impossible to do in general and extremely difficult in practice. This is neither just about the language nor just about the implementation; it's about the consequences of language decisions in the implementation.

> the extra indirection only applies for elements that are boxed primitives

Yes, I just assumed since I had already mentioned primitives it was clear that I'm talking about the use of primitives in generics. But I'll edit it in to repeat myself.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by chrisseaton on Monday December 18, 2017 @07:07PM (#15956675)
> I'm talking talking about the repercussions of decisions in the language that affect the implementation

Well fine I welcome and respect your opinions on this topic, and you're not even wrong, but that's it's not remotely what anyone else is talking about in this thread!

We're talking about what the two main JIT compilers on the two teams have decided to implement, given the constraints they have from their input. We're not talking about how generics were implemented, or language design changes, because we're talking about how the JIT compilers work.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by mehrdadn on Monday December 18, 2017 @07:22PM (#15956740)
In that case, it seems we have a different metric for a JIT compiler being "better"? I was going by the quality of the final output, but you seem to be going by the complexity of the intermediate optimizations it goes through? Which I admit also makes sense, but it's not what I expected: when someone says "is X better than Y", the obvious implication is they should choose X over Y since it would yield a better result, and yet that generally wouldn't be the case here?
Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by chrisseaton on Monday December 18, 2017 @07:32PM (#15956792)
Think about it like this:

Two chefs.

Chef A gets really easy to use ingredients and produces a good dish with them.

Chef B gets rubbish ingredients but spends time doing amazing techniques with them anyway and produces a good dish as well, maybe even a bit better!

If this is all we know about the chefs, I'd say it looks like Chef B is the 'better' chef. It's not their fault they got worse ingredients, and they managed to do a great job with them.

You didn't need Chef B to handle Chef A's ingredients, because they were simple. Perhaps we should thank the supplier for that! But Chef B is still the 'better' chef.

It still might be nice if Chef A could do some of the amazing techniques that Chef B did, even though their ingredients mean they aren't required all of the time. They may help in some cases.

The .NET CLR JIT is Chef A, the JVM's HotSpot C2 JIT is Chef B.

I mean if we judge a JIT just by the quality of the output and don't consider the input, then reducing to absurdity an identity JIT for already-optimised machine code to the same machine code is the best JIT in the world. Clearly it isn't.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by mehrdadn on Monday December 18, 2017 @07:50PM (#15956884)
What you say would make sense in a hypothetical world where every JITter could work with every language, but that's not the world we live in. You can just hand chef B better-quality ingredients and have him do his thing, but you can't just hand HotSpot MSIL code and have it do its thing. Half of this is due to differences in the representations. The other half is because MSIL has features that (as far as I know; please correct me if I'm wrong) the JVM doesn't have, such as by-ref variables, which it would still need to support, but which might make optimizations such as escape analysis harder.

This is why people judge chefs independently from the ingredients they are given, but don't judge languages and implementations independently from each other. In the first case they are actually (mostly) independent in the real world, whereas in the second case they are frequently dependent on each other, and it is not possible to mix-and-match languages with compilers. (But I certainly do hope we get to a point where the latter would be possible, too.)

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by chrisseaton on Monday December 18, 2017 @07:59PM (#15956933)
Your points do make sense.

I would argue that it just isn't the case in practice that MSIL includes anything that would make optimisations that the JVM does significantly harder, but I only have my academic and professional experience working on both systems, nothing that I can cite or prove to you.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by macca321 on Tuesday December 19, 2017 @04:59AM (#15959074)
Is it not that Chef B doesn't have a frying pan (i.e. decent generics) so has to do a lot of tricks?
Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by matthewwarren on Tuesday December 19, 2017 @05:22AM (#15959170)
Thanks for this analogy, I love it!!
Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by srean on Tuesday December 19, 2017 @10:10AM (#15960707)
> If you read my comment,

That was not necessary.

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by kittiepryde on Monday December 18, 2017 @06:11PM (#15956318)
Are there standard benchmarks used to measure and compare the two approaches (jvm vs .net)?
Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by benaadams on Monday December 18, 2017 @06:48PM (#15956552)
Pinch of salt with all benchmarks, but "The Computer Language Benchmarks Game"?

http://benchmarksgame.alioth.debian.org/u64q/csharp.html

.NET does better in most of them, but falls down vs Java on Regex and k-nucleotide

Re:A Look at the Internals of 'Tiered JIT Compilation' in .N... by chrisseaton on Monday December 18, 2017 @06:21PM (#15956369)
It's crazy but I'm not really aware of any good benchmarks, at least in the research community.

But you can show the differences qualitatively, in that the .NET simply doesn't have large swathes of optimisations which I think are considered pretty fundamental in the JVM such as escape analysis.