3 ms·
By pushing things into the language, what I mean is that for example C# has stack allocation and the JIT is a very straight line compiler (for many years it was
by peoplewindow 9y ago
By pushing things into the language, what I mean is that for example C# has stack allocation and the JIT is a very straight line compiler (for many years it was basically a C++ compiler, opts wise). The Java guys refused to add this complexity to the language and instead implemented escape analysis and scalar replacement. Now with Graal they're doubling down on that approach: there are no proposals to add stackalloc to Java, but Graal is capable of eliminating allocations in far more cases than previously. In other words Java can automatically mark things as stackalloc (sorta) without the user thinking about it, and it gets better over time. Whereas C# code does not get less allocation heavy over time.
A more obvious example is value types. CLR guys put value types into the runtime and type system. Now Java is going in that direction too, but actually, the Truffle guys have demonstrated that they can specialise data structures to get the same layouts that value types give you on the fly with compiler techniques again (e.g. List<Integer> is compiled to List<int> behind the scenes when possible). And both C2 and Graal inline code more aggressively than the CLR does, and when functions are inlined together more EA is possible, so that's like passing data by value instead of by reference. So it's not really clear that Valhalla is going to be necessary in the end, if that line of compiler research is pursued further, and over the years I've been revising what I anticipate the performance improvements to be from it downwards.
And finally Spans in C# are yet another example of this. Java has ByteBuffer which provides a similar abstraction, but it doesn't do e.g. array slices or access to the stack. But then again, you hardly need to think about the stack when writing Java because the runtime will use it most of the time the human would have done anyway, and the collections API offers sub-array access with inlined and fully optimised accesses. I would note that Go and C++ are both designed with AOT compilation in mind and neither are widely held up as examples of excellent language design.
Overall, it's not clear that we've reached the limit of what runtimes can do. It seems more likely we've reached the limit of what runtimes written in C++ can do before they hit the sort of complexity scaling limits that make Java and C# so widely used to begin with. The speed with which the Graal/Truffle guys have been able to develop new optimisations that were theoretical for years with the C++ compiler is remarkable - even things where the more traditional branch of Java development is considering .NET style language complexification to get it.