4 ms·
Performance is scarcely mentioned. It probably doesn’t matter that much for a build system. But for projects where it does matter, you won’t get performance in
by skybrian 1y ago
Performance is scarcely mentioned. It probably doesn’t matter that much for a build system. But for projects where it does matter, you won’t get performance in the same ballpark as a Lua interpreter written in C if you use Go.
In particular, because Go is memory-safe, you don’t have the control over memory layout you need to do tricks like NaN-boxing. Anything that requires a union with a pointer (which will be every value in a dynamically typed language) must be represented as a value of interface type, and interface values are quite fat - 16 bytes on a 64-bit machine.
Interpreters are atypical programs to optimize. Few other programs use unions so much in their inner loop.
- foldr 1y agoYou can do raw memory access via the ‘unsafe’ package, so I don’t think it would be impossible to do NaN boxing in Go. It would be somewhat less convenient than in C.
- skybrian 1y agoUnlike C, Go is garbage collected. Hiding pointers from the garbage collector so it can’t trace them without breaking something seems tricky. There would need to be pointers to that memory somewhere else to prevent it from being collected. And then since you’ve disabled the system GC, you need to write your own GC that understands NaN boxing to find out when memory can really be freed. I see it as so awkward that it’s not worth doing.
- shadowgovt 1y agoThere are some advantages to constraining our runaway pointers to the part of the language written under the `unsafe` package, as opposed to doing the whole thing in C where we get the advantages of no language preconceptions of garbage collection getting in the way but the disadvantages of forever having to wonder whether we have vulnerabilities in the bog-standard steps like "reading from the input file."
- pjmlp 1y agoOr do it like C in the age of K&R C, and compilers ramping up for C89 compliance, with a little bit of Assembly. Most stuff people use in C for writing interpreters with optimal performance, isn't ISO C, rather C compiler specific extensions, or inline Assembly. All things being equal, same rules apply.
- skybrian 1y agoIt’s different because Go is garbage collected. See my other reply.
- pjmlp 1y agoNo it is not, that is the anti-GC folks agenda since Xerox PARC days, placing all GC languages into one big basket, not learning what actually makes one specially tick, the language features available for low level coding in each programming language and such. Just sticking to the old ways is why we don't get progress in some industry corners.
- skybrian 1y agoI’m not anti-GC. There’s nothing wrong with using a garbage collected language. However, if you use a built-in garbage collector, you do need to play by its rules, or it’s not going to work. These rules are language-specific and limit what you can do efficiently when writing an interpreter, versus writing your own GC that’s purpose-built. For example, Go’s garbage collector isn’t going to do as well at JavaScript as V8’s garbage collector, because the only unions it understands are Go interfaces. Also, the garbage collectors for other languages mostly don’t support some features of the Go language, such as taking pointers into the middle of objects. You can still write an interpreter in any language, but there will be an efficiency cost when the languages are too different.
- pjmlp 1y agoI would say it is a matter of implementation, taking the best advantage of unsafe, Assembly, value types and generics. Not everything has to try to replicate C in language XYZ. But I do agree, among all languages I would rather reach out for D, C#, any of the MLs or Haskell, Lisp or Scheme variants, instead of Go. Also if ultimate performance is the goal, then nothing beats handwriten Assembly, so that places both C and GC languages out of the game, as Android has been doing since Android 7, in case there is no PGO data available for the JIT.