Live data from Hacker News

An attempt to articulate Forth's practical strengths and eternal usefulness

im-just-lee.ing

21–30 of 68 posts

Re: An attempt to articulate Forth's practical strengths and eternal usefulness

#21
There is an aspect of the history of Forth and C I have been trying to wrap my head around.

The early B compiler was reported to generate threaded code (like Forth). The threaded code was abandoned fairly early in the port to the PDP11 from the PDP7 as it was deemed to slow to write an operating system in.

At which point unix and C lost a very interesting size optimization. With the net result that Forth was more portable and portable between machines circa 1970 and Unix had to wait until circa 1975 with UnixV6.

I have been trying to go back through the history to see if I could understand why threaded code was deemed too slow. Today the most part of executables is code that is not run often and would probably benefit from a smaller representation (less memory and cache space making the system faster overall). So this is a practical question even today.

I found a copy of unix for the PDP7. Reproduced from old printouts typed in. If I have read the assembly correctly the B compiler was not using an efficient form of threaded code at all.

The PDP7 is an interesting machine. It's cells were 18 bits wide. The adress bus was 12bits wide. Which meant there was room for an opcode and a full address in every cell.

As I read the B compiler it was using a form of token threading with everything packed into a single 18 bit cell. The basic operations of B were tokens and an if token encoded with a full address in the cell. Every token had to be decoded via a jump table, the address of the target code was then plugged into a jump instruction which was immediately run.

Given the width of the cells, I wonder what the conclusions about performance of B would have been if subroutine threading or a similar technique using jmp instructions would have been.

Does anyone know if Forth suffers measurably in inner loops from have to call words that perform basic operations?

Is this where a Forth programmer would be accustomed to write the inner loop in assembly to avoid the performance penalty?

Re: An attempt to articulate Forth's practical strengths and eternal usefulness

#22
Oh, cool! SmithForth[0] is how I originally learned about x86-64 microarchitecture. It's a Forth that bootstraps off hand-coded x86-64 opcodes. I decided to go the other direction and decompile the binary by hand. It really is a beautiful piece of code. Highly recommended reading.

Also, you're excited by Forth and Lisp, you might like Forsp[1]. It uses a call-by-push-value evaluation strategy in a way that really makes the language feel like a true hybrid of the two. The implementation is also brilliantly simple.

Anyway, thank you for the article. I lurk on the DuskOS mailing list and wish I could find out where the Forthers gather IRL so I could osmote more of their world into my own.

[0]:https://dacvs.neocities.org/SF/

[1]:https://xorvoid.com/forsp.html

Re: An attempt to articulate Forth's practical strengths and eternal usefulness

#23
post #4

I like the spirit of this article, but I find it strange that they open their article by quoting me, but then don't include Dusk OS's C compiler in the list. Fairly counting SLOC is a tricky problem, but my count is 1119 lines of code for the C compiler (written in Forth of course), that's less than 8x the count of chibicc, described as the smallest.

(typing from phone) i simply had not known. it is a great example of a short path to a c dialect then! merci pour votre travaille au dusk et collapse! i will add a paragraph about it to the essay. this took me many days to write and many revisions and still i see it isnt perfect!

note the point of that section was really that anyone using gcc or clang should ack. the real cost when using them.

Re: An attempt to articulate Forth's practical strengths and eternal usefulness

#24

There is an aspect of the history of Forth and C I have been trying to wrap my head around. The early B compiler was reported to generate threaded code (like Forth). The threaded code was abandoned fairly early in the port to the PDP11 from the PDP7 as it was deemed to slow to write an operating system in. At which point unix and C lost a very interesting size optimization. With the net result that Forth was more por…

I can probably shed some light on that. I've used Forth on 8 bit platforms (6502, 6809), 16 bit platforms (80286) and 32 bit platforms (68K), as well as assembly, and on the 16 and 32 bit platforms C. Putting these side-by-side and assuming roughly equivalent programmer competence levels at the time assembler would win out, C would get you to maybe half the speed of assembly on a good day and Forth was about 10x slower than that.

Which was still incredibly fast for the day, given that Forth was compiled to an intermediary format with the Forth interpreter acting as a very primitive virtual machine. This interpretation step had considerable overhead, especially in inner loops with few instructions the overhead would be massive. For every one instruction doing actual work you'd have a whole slew of them assigned to bookkeeping and stack management. What in C would compile to a few machine instructions (which a competent assembly programmer of the time would be able to significantly improve upon) would result in endless calls to lower and lower levels.

There were later Forth implementations that improved on this by compiling to native code but I never had access to those when I was still doing this.

For a lark I wrote a Forth in C rather than bootstrapping it through assembly and it performed quite well, Forth is ridiculously easy to bring up, it is essentially a few afternoons work to go from zero to highway speeds on a brand new board that you have a compiler for. Which is one of the reasons it is still a favorite for initial board bring-up.

One area where Forth usually beat out C by a comfortable margin was code size, Forth code tends to be extremely compact (and devoid of any luxury). On even the smallest micro controllers (8051 for instance, and later, MicroChip and such) you could get real work done in Forth.

Re: An attempt to articulate Forth's practical strengths and eternal usefulness

#26
post #25

I often use a heavily forth inspired script language in my bigger c# projects. I have a hidden repl and can input scripts. I like how easy it is to produce results with such low vocabulary. Also there is no expression parsing

Sounds cool, as someone interested in concatenative languages and also a user of C#, might I ask if you have a link?

Re: An attempt to articulate Forth's practical strengths and eternal usefulness

#27
Article is lame in multiple ways, and also eForth was written by Bill Muench. Dr Ting adopted Muench's version to use assembly language bootstrapping instead of metacompilation. Bootstrapping is possibly easier for beginners to understand, but metacompilation is part of Forth's fiendish cleverness and it's a shame for an aficionado to miss out on it.

Re: An attempt to articulate Forth's practical strengths and eternal usefulness

#28

There is an aspect of the history of Forth and C I have been trying to wrap my head around. The early B compiler was reported to generate threaded code (like Forth). The threaded code was abandoned fairly early in the port to the PDP11 from the PDP7 as it was deemed to slow to write an operating system in. At which point unix and C lost a very interesting size optimization. With the net result that Forth was more por…

It is no so much the parts of the code that run infrequently that contribute to poor performance, but the very tiny The overhead of threading seems pretty obvious: call and return instructions are expensive compared to the cost of the one equivalent instruction that would have been executed in a compiled implementation. And placing arguments on a stack means that all operands have to to be read from and written to memory, incurring additional ferocious overhead, whereas a compiler would enregister values, particularly in performance-critical code. Not unreasonable to expect that Forth code is going to run at least an order of magnitude slower than compiled code.
Post reply on HN