Live data from Hacker News

How to make a fast dynamic language interpreter

zef-lang.dev

21–30 of 67 posts

Re: How to make a fast dynamic language interpreter

#21
post #19

In a similar vein, see this page about the performance of the interpreter for the dynamic language Wren: https://wren.io/performance.html Unlike the Zef article, which describes implementation techniques, the Wren page also shows ways in which language design can contribute to performance. In particular, Wren gives up dynamic object shapes, which enables copy-down inheritance and substantially simplifies (and hence a…

That’s basically what is done all the time in languages where monkey patching is accepted as idiomatic, notably Ruby. Ruby is not known for its speed-first mindset though.

On the other side, having a type holding a closed set of applicable functions is somehow questioning.

There are languages out there that allows to define arbitrary functions and then use them as a methods with dot notation on any variable matching the type of the first argument, including Nim (with macros), Scala (with implicit classes and type classes), Kotlin (with extension functions) and Rust (with traits).

Re: How to make a fast dynamic language interpreter

#22
The jump from change #5 to #6 (inline caches + hidden-class object model) doing the bulk of the work here really tracks with how V8/JSC got fast historically — dynamic dispatch on property access is where naive interpreters die, and everything else is kind of rounding error by comparison. Nice that it's laid out so you can see the contribution of each step in isolation; most perf writeups just show the final number.

Re: How to make a fast dynamic language interpreter

#24
post #15

Earlier quoted context omitted.

Lua is way more dynamic

I suppose it depends on where you are looking for dynamicity. In some ways, lua is much more laissez faire of course. But in Python, everything is an object, which is why, as I said, it spends much of its time looking things up. And things like bindings for closures are late, so that's more lookups as well. In lua, many things aren't objects, and, for example, you can add two numbers without looking anything up. Anot…

Nop, Python is not full object. Not even Ruby is fully object, try `if.class` for example. Self, Smalltalk, Lisp, and Io are fully object in that sense. But none as far as I know can handle something like `(.class`.

Re: How to make a fast dynamic language interpreter

#25
post #15

Earlier quoted context omitted.

I suppose it depends on where you are looking for dynamicity. In some ways, lua is much more laissez faire of course. But in Python, everything is an object, which is why, as I said, it spends much of its time looking things up. And things like bindings for closures are late, so that's more lookups as well. In lua, many things aren't objects, and, for example, you can add two numbers without looking anything up. Anot…

Nop, Python is not full object. Not even Ruby is fully object, try `if.class` for example. Self, Smalltalk, Lisp, and Io are fully object in that sense. But none as far as I know can handle something like `(.class`.

You obviously realize that different languages have different syntactic requirements, yet you are willing to cut one language a break when its minimal syntactical elements aren't objects, and refuse to cut other languages a break because they have a few more syntactical elements?

Re: How to make a fast dynamic language interpreter

#26
post #19

In a similar vein, see this page about the performance of the interpreter for the dynamic language Wren: https://wren.io/performance.html Unlike the Zef article, which describes implementation techniques, the Wren page also shows ways in which language design can contribute to performance. In particular, Wren gives up dynamic object shapes, which enables copy-down inheritance and substantially simplifies (and hence a…

Yes, language design is a hugely important determinant of interpreter or JIT speed. There are many highly optimised VMs for dynamic languages but LuaJIT is king because Lua is such a small and suitable language, and although it does have a couple difficult to optimise features, they are few enough that you can expend the effort. It's nothing like Python. It's not much of an exaggeration to say Python is designed to minimise the possibility of a fast JIT, with compounding layers of dynamism. After years of work, the CPython 3.15 JIT finally managed ~5% faster than the stock interpreter on x86_64.

Re: How to make a fast dynamic language interpreter

#27
post #15

Earlier quoted context omitted.

I suppose it depends on where you are looking for dynamicity. In some ways, lua is much more laissez faire of course. But in Python, everything is an object, which is why, as I said, it spends much of its time looking things up. And things like bindings for closures are late, so that's more lookups as well. In lua, many things aren't objects, and, for example, you can add two numbers without looking anything up. Anot…

Nop, Python is not full object. Not even Ruby is fully object, try `if.class` for example. Self, Smalltalk, Lisp, and Io are fully object in that sense. But none as far as I know can handle something like `(.class`.

Aren't you mixing up syntax and the concepts it expresses? Why would (.class have to be a thing? Is space dot class a thing? I don't think this makes sense and it doesn't inform about languages "being fully object". Such syntax is merely for producing an AST and that alone doesn't mean "object" or "not object". It could just as well be all kinds of different things, or functions, or stack pushes and pops or something.

Re: How to make a fast dynamic language interpreter

#28

Earlier quoted context omitted.

I bet LuaJIT crushes Zef! Or rather, I would hope that it does, given how much more engineering went into it There are many runtimes that I could have included but didn’t. Also, it’s quite impressive how much faster PUC Lua is than QuickJS and Python

Because QuickJS is really slow. Don't be fooled by the name. It's almost an order of magnitude slower than node/v8. (I suppose the quick in QuickJS means "quick for a pure interpreter without JIT compilation or something...)

[deleted]

Re: How to make a fast dynamic language interpreter

#29

The jump from change #5 to #6 (inline caches + hidden-class object model) doing the bulk of the work here really tracks with how V8/JSC got fast historically — dynamic dispatch on property access is where naive interpreters die, and everything else is kind of rounding error by comparison. Nice that it's laid out so you can see the contribution of each step in isolation; most perf writeups just show the final number.

I agree, but there’s a tiny caveat that this is for one specific benchmark that, I think, doesn’t reflect most real-world code.

I’m basing that on the 1.6% improvement they got on speeding up sqrt. That surprised me, because, to get such an improvement, the benchmark must spend over 1.6% of its time in there, to start with.

Looking in the git repo, it seems that did happen in the nbody simulation (https://github.com/pizlonator/zef/blob/master/ScriptBench/nb...).

Post reply on HN