Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Threaded Code (1999) (tuwien.ac.at)
72 points by tosh on May 7, 2021 | hide | past | favorite | 25 comments


http://nominolo.blogspot.com/2012/07/implementing-fast-inter...

I've been interested in this lately. I keep getting the feeling that it, like lots of programming knowledge, remains locked up in the minds of a limited set of greybeards.

Not entirely the same thing, but Mike Pall wrote luajit2 mostly by himself. The interpreter alone is faster than the original luajit.

When I see how much small teams like the lua team and Mike have done, I know there is massive inefficiency in our industry. We got caught up in the new hotness and we discard all of the knowledge of the past, to our own detriment.


I guess this is, at least to some degree, caused by code reusability. We can easily (with the right PL) plug foreign code into our project and use it. We cannot as easily read a paper, or a low-level implementation for a different instruction set and use the method in our project. Hence we prefer the former over the latter. I for instance once implemented Derek Oppen's pretty printer in C++ and was surprised how difficult such a transcription was.

This situation then leads to a certain inefficiency, as portability becomes more important than efficiency.

On top of that, there is the cost of maintaining a piece of software. A threaded forth interpreter is much more expensive to maintain then one based on a switch statement, I'd assume.


I beg to differ. Going to lower level code usually results in much simpler codebase for things like implementing coroutines, threaded code etc.

Take z-machine for example. It was apprarantly so much easier to code a z-machine interpreter in Assembly for each architecture and run bytecode on it.

Who says assembly doesn't have code reusability. You can easily translate between architectures if you stay away from instruction set specific tricks. For me, assembly is a universal abstraction for how my computer works. I know it's not accurate, lots of magic happens on microcode and OS level, but still it's so much cleaner.

Going to higher level languages has many advantages, and I would definitely prefer to write any complex project (for example a web browser) with the help of higher level languages.

However learning and programming in Assembly broadened my horizon in a lot of ways.

Comparing C++ to Assembly in terms of complexity is not fair. C++ is "complex", it requires loads of tooling to compile, a special runtime etc.

Assembly is super simple at its core. Especially if you can free yourself from structured code ideology. C and C++ force you into programming a certain way, you don't use jumps, you can't manipulate the stack however you want etc. Once I leave all that and start playing with real spaghetti code :) with jumps all over the place, programming gets much more fun for me.

The cost of maintaining assembly code doesn't have to be high. You can write special subroutines you need in Assembly and keep the code short, simple and useful. I think it's a misperception that assembly is hard to maintain. I think people think that because lots of developers are afraid to even touch C code, let alone Assembly.

TL;DR Assembly is fun, leave everything you think you know about programming and jump in :).


> Especially if you can free yourself from structured code ideology.

.. how well does this work in a team? There are a number of people who do individual heroics in assembly, but I'm not aware of any large long term maintained such projects that have outlived their originator.


Maintaining projects in assembler requires much less heroics than developing them. Significant part of Soviet computer program, shortly before (Minsk 32), and after they switched to cloning IBM mainframes (ES EVM), was maintained in assembler only, once they lost access to the original PL/S source code of the OS and other system products. These were teams of many people and the activity lasted long enough time to fit your criterium. They certainly outlived the originators by several dozen years.

Maintenance involved fixing bugs (including in the OS kernel), localizing software to a different language (sounds inoffensive ... when you have source code. Much more nasty when translated sentence doesn't fit into its allocated place in the binary). And adapting to hardware difference, such as less RAM, less capable peripherals and slower CPUs.

EDIT: Minsk 32 was bespoke development but the language still was close enough to hardware to be qualified as assembly by today's standards.


Thanks for this anectode! Soviet CS history is very interesting. There were some novel ideas.

I was fascinated by DRAKON when I first learned about it. The Wikipedia article said that it was used by other professions as well. For example doctors had flowcharts in DRACON for medical procedures etc.

I'll be glad (and think that the whole community will be glad) if you decide you want to share more historical anectodes about the Soviet computer program.


> Especially if you can free yourself from structured code ideology

What is "structured code ideology"?


Like every other programming paradigm, structured programming is also a paradigm. The only difference is that it is so engrained in us that we don't see it. Like each programming paradigm it is an ideology for me.

Why is it acceptable to refuse OOP and not code using objects and not refusing for loops, if statements etc.? It is because we are taught to program and think like that. I am not saying this is wrong, but there is so much more to programming if one can break free from structured programming paradigm. All the loops, variable declarations, scoping, if statements, switch statements etc. are inventions just like constructs of object oriented or [insert programming paradigm here] programming. CPUs don't have these constructs. These are abstractions and limitations to make life easier. But there is much more to programming if you take a step deeper.


This is an illuminating viewpoint. I came to Assembly from HLLs and had often wondered why i found writing assembly code so alien and difficult (in spite of understanding Computer Architecture). I was restricting myself by looking at it only through the lens of Structured Programming constructs. Only by going beyond these concepts and embracing the full generality of Assembly can one understand many techniques like Threaded Code/Self-modifying code etc.


Great comment and quite insightful !


why is this message grayed-out?


When people downvote a comment it gets grayed-out to make it harder to read.


In my case, it generally just makes me want to read it more, to see what the fuss is about.


The big complexity in software is where it interfaces to business problems and interacting with humans.

Where there is a defined task such as language interpretation or codec conversion (ffmpeg), there a virtuoso programmer or small team can really produce some amazing work.


I wrote an article recently on a C-based fast interpreter technique that generates code comparable to hand-written assembly. I have an example where I specifically match some LuaJIT 2 assembly code in C: https://blog.reverberate.org/2021/04/21/musttail-efficient-i...


Makes me wonder how much faster the Gforth interpreter could be if it weren't committed to portability.


The VFX Forth compiler is about 3 to 3.5 times faster on most benchmarks. GForth-fast does some clever "JIT" type tricks to make it faster than a naive Forth system but there is still some overhead inherent in reading the lists of addresses in threaded code.


Right, the Gforth project makes use of lots of clever techniques, but they're not interested in conventional optimising native-code compilation (whether JIT or ahead-of-time) and if I understand correctly they're not interested in writing platform-specific code (i.e. hand-optimised assembly).

On another note, Gforth is actively being worked on, but it's been almost 7 years since the last stable release.


I don’t see a definitive date on this article but assume it’s 10 or more years old. It mentions the Pentium 4 as a “modern” CPU—a CPU produced from 2000-2008 and succeeded by the Core 2.

What has changed since then, and especially beginning with Haswell, is that contemporary CPUs have so much more branch prediction machinery that they can render computed goto techniques irrelevant. It’s a neat technique, for sure, but people looking for performance this decade need to look away from threaded code techniques and towards ILP and SIMD.


If you can tolerate/ignore some of the crazies on the news group, the author is routinely on comp.lang.forth.

You could ask.


Internet Archive has it back as far as 1999, so I've put that year above, though it could well be older. Not much older, though, since there's a 1996 reference in there.

https://web.archive.org/web/19990117022746/http://www.compla...


Slightly confusing with the other meaning of threading, this is more like what is pejoratively called "spaghetti code" which was mostly superceded by structured programming. Easier to understand, marginally less efficient, especially for the interpreter case.


No, it's nothing like that. It's a method for implementing interpreters that works well for Forth. It has absolutely nothing to do with 'spaghetti code' or structured programming.

In this case, the term 'thread' is the same in both usages. The confusion is that people started using 'multithreading' and 'threading' interchangeably. The concept of a 'thread' existed before Forth and any form of multitasking were invented, and MVT (which used the term 'task' rather than 'thread') and Forth were both invented around the same time.

I'd recommend you read the Wikipedia page for 'Threaded code': it's much clearer than the linked page, and will give some background of the purpose behind it. Most interpreters that don't do something like walking an AST do some form of it, even if that's by using some kind of bytecode. If you've ever seen code written using continuation-passing style, it's implementing a form of threaded code.


Threading can be a fairly significant speedup for most VM interpreters, and an optimization often worth making in cases where performance matters.


It is often used as a perjorative but the spaghetti is in the eyes of the beholder.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: