4 ms·
There actually is a really good compiler reason to not allow subtyping concrete types, and it's one of the main reasons Julia code is faster than languages like
by adgjlsfhk1 4y ago
There actually is a really good compiler reason to not allow subtyping concrete types, and it's one of the main reasons Julia code is faster than languages like Java. If you allow concrete types to have subtypes, when you see `Vector{Int}` (List<Integer> in Java), the compiler can't tell what the memory layout of the element type will be. As a result, pretty much all objects end up boxed which destroys locality and removes all possibility for vectorization. In Julia, the compiler knows the memory layout of any insatiable type at compile time, so it can much more aggressively remove pointers (or even just decide that an object will exist in registers rather than allocating memory for it).
- blindseer 4y agoThanks for that explanation!
- kaba0 4y agoI don’t see how is it inherent to subtyping, but language semantics. For example Java will likely add 2 new types of class that will loose identity - at that point Integer (and other, struct-like data) will be optimizable by inlining into the surrounding data structure.
- Sukera 4y agoThe point is not limited to Int though. Say you have this struct: struct MyStruct a::Int64 b::Float64 end Since the size of each field is known (8 bytes), the size of the whole struct, and thus the size of each instance of that struct, is known - 16 bytes. This is crucial information for inlining, loop unrolling, copy elision, deciding which register(s) to place the object in, getting rid of indirections through pointers.. If you'd allow to subtype MyStruct, the compiler wouldn't be able to know ahead of time what the size of a MyStruct object is and would either have to box every access (introducing pointers which have to be chased on access) or defer A LOT of work to runtime. With boxing, you almost immediately lose lots of opportunities to SIMD or otherwise optimize your code, because you have to keep a whole lot of extra type information around at runtime that's just not necessary when all your objects in a e.g. Vector{MyStruct} have the same size anyway.
- kaba0 4y agoOh I see what you mean. Though that’s why Java has the `final` keyword to forbid subtyping for a given type.
- adgjlsfhk1 4y agoright. The Julia design is to say that `final` was a good idea and that everything should have it (Especially since OOP people now say to prefer composition to inheritance anyway).
- languageserver 4y agoyou misunderstand both Java generics and Java primitive types. 1. the JVM does not support generics as a language construct, and are simply a compiler feature of Java 2. the JVM and Java differentiates primitive and reference types, Integer being a reference (boxing) type of the primitive type int. And, generics do not support primitive types anyway. The JVM implementations are incredible pieces of machinery, and even if they did not pack or stride their primitive arrays -- which they absolutely do -- the JVM & compilers will handle an incredible amount of runtime memory layout and packaging.
- IshKebab 4y agoThat's not a result of `int` not being subtyped. It's a result of forcing reference semantics on everything (which is something most languages unfortunately do). C++ doesn't need this kind of restriction because it makes the difference between references and values explicit, so it's actually possible to explicitly ask for a vector of values, rather than only being able to ask for a vector of references and artificially restricting the language so that it can be optimised to a vector of values. (Yeah I know you can't derive from int in C++ but that's for other reasons.)
- adgjlsfhk1 4y agoJulia also has reference semantics for everything. That said, it turns out that if you make it idiomatic to create immutable structs, the difference between reference semantics and copy semantics disappears, and lets the compiler pick the faster one (which fixes a common performance bug in C++ where users end up copying a ton of data around by accidentally copying a bunch of data)
- IshKebab 4y agoYeah I always thought that "make everything immutable!" was partly - maybe even mostly - a workaround for the fact that it's so hard to copy data in most languages. I agree C++ makes it too easy to accidentally copy data, but at least you can copy data!
- adgjlsfhk1 4y agobut the only reason you want to copy data is that it makes manual memory management easier. otherwise paying a reference is almost always cheaper.