Hacker News new | ask | show | jobs
by whizzter 1040 days ago
Value types was in the CLR(_Common_ Language Runtime) from day one as the runtime supported (variations of) C/C++,etc. Iirc proper generics didn't appear in version 1 of C# but since the foundation was there generics could become an addon in terms of new collection classes that could be properly parametrized.

Java generics took a shortcut by reusing the old classes and just layering them on in the language but erasing all useful information to the runtime, and this is what's biting them in the back now when practice has shown that flat memory layouts is highly beneficial in terms of performance as CPU speeds has outstripped memory latencies.

A List<int> in C# will be 2 objects, the List object and the underlying int[] array of sequential numbers, a Java List<int> will be 2+N objects, the List object, the object[] array and N boxed int objects, and the if N int objects are scattered in memory then traversing the integers will be far more expensive due to memory latencies.

2 comments

Generics were also already on an experimental branch by the time .NET 1.0 was released.

Microsoft decided not to delay the release waiting for them to get ready.

Don Syme of F# fame has a couple of blog posts with the history of generics in .NET, as he was part of the original design team.

Regarding List<int> and specializing it to an int[] has more to do with generics than value types. The most important semantic info about a value type is not having identity, that is modifying it is not observable from another thread that were holding the same value previously.

This alone lets one do things like freely copy/share/modify them, that directly allows for flattening.

In theory you're right, in practice however the details of the JVM instruction set and the existing generics system throws wrenches into it.

The JVM has instructions like iload, aload, dload,etc (integer, reference, double) to load values from stack slots, the simple instructions were probably chosen to support direct HW execution that was attempted for various embedded Java scenarios. They were unwilling to extend the instruction set back in the day when generics were introduced due to these type specific instructions and they just decided that everything generic could be an object.

The CLR(.NET/C#) equivalent of iload,aload,etc is ldloc , a single instruction whose type depends on the stack slot, generic classes "just" need to specialize the type of slots,etc to have a specialized class, be it a primitive, reference or value.

What they're doing now according to the article is to make aload and the a- family of instructions behave more like the CLR counterparts by adding slot flags, analysis and optimizations to detect "value-cases", so List<int> would be List<Integer(notnull)> and then optimized back down to List<int>.

It's basically a hack upon the hack because they want to preserve backwards compat to the previous hack. If they can get the engineering sorted then sure, I'm mostly glad I won't have to maintain any code related to all this machinery.

And I'm quite curious about how the JVM-lang ecosystem feels about this, maybe they're open to it if it solves backwards compat under the hood for them also, but I wouldn't be surprised if we're going to see pre-JVM 25 versions in addition to post JVM 25 versions of JVM langs in some cases.