3 ms·
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 surpas
by sreque 9y ago
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.
- naasking 9y agoThe .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.
- seanmcdirmid 9y agoThe 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).
- throwaway010317 9y agoI 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
- naasking 9y agoYou can see a few tricks in my project here: https://github.com/naasking/Dynamics.NET 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/Dapper.Compose/Query.cs#L90 https://github.com/naasking/Dapper.Compose/blob/master/Dappe... [2] https://sourceforge.net/p/sasa/code/ci/default/tree/Sasa.Collections/Trie.cs https://sourceforge.net/p/sasa/code/ci/default/tree/Sasa.Col...
- pron 9y agoI 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.