4 ms·
I 've never understood the point of JITing. Just compile the thing once for your target architecture and you're done. No more spawning threads for doing the sam
by zeroc8 4y ago
I 've never understood the point of JITing. Just compile the thing once for your target architecture and you're done. No more spawning threads for doing the same thing over and over again. I'm glad that languages like Go and Rust are bringing back the lost simplicity of yesteryear's dinosaur languages. Life can be so easy.
- lillecarl 4y agoReflection in C# is a thing, it isn't in either Go or Rust. I've read some kind of compiler shenanigans can get something that resembles reflection in C++. I love reflection, the fact that libraries can look at your types is really really cool. Not saying it can't be done with a compiled language but I don't see it anywhere. Being able to load a shared library, search it for classes implementing interfaces, instantiate them and call their methods is pretty slick too.
- pjmlp 4y agoGo has reflection, and you can make use of compile time reflection on Rust via the macros infrastructure.
- lillecarl 4y agoDoes that cover all mentioned usecases though? They're discussing source generation in this thread, not even close to the same thing (for certain usecases)
- pjmlp 4y agoKind of, you can use the parsing package for that, alongside the //go:generate infrastructure. Or you can use Go reflection package and generate the source code from it. Of if wanting to do something like Assembly.Emit, generate the machine code directly with a little help from unsafe and syscall packages. Depends pretty much on the actual use case.
- pjmlp 4y agoIBM OS/400 binaries (nowadays IBM i), can be executed in a completly different architecture from 1988, without any changes, possibly the source code doesn't exist anymore, while taking full advantage of IBM Power10 on its last iteration. Same applies to any other bytecode format making use of dynamic compilers.
- to11mtm 4y agoJitting is useful for things like dynamic loading/dispatch and simplifying distribution of libraries around it. FBOW it's worth remembering the 'cruft' and legacy around .NET's Architecture designs and choices, even if some of the assumptions were wrong. 1. .NET seems to have been originally built under a heavy assumption that the framework was installed on a device. This could be a huge advantage for smaller/embedded devices of the time, if you were working 'close to framework' (as was the style at the time, NuGet wasn't a thing for the better part of a decade after .NET was introduced) you could get a surprisingly compact deployment object. Many of the 'in-house' apps I wrote with clickonce, the cert validation seemed to take longer than the network transfer on upgrade. 1.1: VERY worth noting, the idea that .NET browser plugins would compete with Java plugins; JIT is probably important to do this sanely. 2. Speaking of assumptions, I'm willing to bet that around the design time of many .NET particulars, they were still reeling from the pains of both Win16->Win32 breakages (Win95, Win98), Win16->NT breakages (NT4.0, 2K), Win32/WinNT breakages (XP), and X86/X64 breakages (Server 2003). JIT, alongside a framework API with strongly contracted public members [^0] allows problems to be fixed without vendors necessarily having to provide updated libraries [^1] 3. CAS (Code Access Security) and 'Partially Trusted code'. This somewhat ties back into 1.1, because the idea was that code had to have a certain level of 'verification' around what it was doing, what libraries it was calling, and whether that code -should- be allowed to execute such on a box. I'm thinking of scenarios where an 'intranet' app could have access to a local MSSQL database and open/write files, but an 'internet' app could not. Implementing such via a JIT is far simpler. 4. The combination of Generics and reflection complicate things. To be more specific, the way .NET handles generic methods, basically any reference types (objects) will share the code, as the size of the generic parameter(s) is going to be the size of a reference on the target platform. But in the case of a Value Type (structs), I'm 99% the runtime requires specific code for every different struct[^2] type that is slotted into one of the generic types of a class/method. 5. Simpler dynamic-ish code generation. One of the most lovely (if unloved/ignored) APIs in .NET is the Expressions namespace. [^0] By this I mean there is a -strong- slant towards .NET APIs retaining existing behavior even if it is wrong/subpar, if that behavior is part of the accepted contract. [^1] How well this worked out in practice, probably not so much. I remember my first experience with NET 1.0/1.1 versioning/deployment hell and going back to C++ for a few years. It wasn't until my apps had semi-complex UIs (i.e. not console and multi-window) alongside the renaissance of 3.5 that .NET became a more efficient workflow than the sometimes daunting MFC/ATL C++ winforms workflow. [^2] AFAIK the runtime cannot share struct implementations between two structs with the same layout (I -think- go generics can based of GCShape but maybe not, I'm not a gopher,) but would be delighted to hear otherwise.