by Jeff Fox
The First 10x in Forth
Forth had a surge of popularity in the seventies when FIG was distributing source and alternatives were limited. Many users who discovered Forth at that time reported elation at the increase in their productivity. They wrote programs faster, they debugged them faster, they maintained the more easily. They reported that they could write much smaller and much faster programs that could do much more than the ones they could write before. But when they reported that they had seen a 10x improvement after switching from … they were often dismissed by mainstream programmers as kooks because that just seemed too good to be true to many people.
Those who were there know that the 10x is not all that remarkable and is really due a bunch of numbers that when all multiplied together equals 10. No single thing gave these programmers a way to be ten times more productive, instead it is all the factors multiply by one another.
The reasons have to do with the design of Forth. Stacks, words, blocks. Having the data stack for data is simple and beautiful way to handle and pass data within a program. It introduced less bugs than environments where programmers were working with lots of named variables or where they had to juggle register use by hand in assembler. The separation of data and return stacks made factoring more attractive. If you don’t have to construct stack frames and move data in and out of function call’s local variable data space before you call something you have less overhead in calling a function and can factor the code more extensively. “Factor, factor, factor. Factor definitions until most definitions are one or two lines.” is Chuck’s advice.
Factoring was a key to debugging and maintaining the code. Well factored code is easy to debug and maintain so the programmer is more effective with their time. Factoring also helps achieve the desired balance between memory use and speed for a given machine since memory and processing power are always finite.
Programs were often performance limited by their interaction with mass storage as they are today. Forth provided the BLOCK mechanism as a very simple form of virtual memory and close to the metal mass storage access. By using BLOCKS where they could for data instead of more complex file access programmers reported speeding up parts of their programs by 100x as well as making them smaller and simpler.
Programmers often also reported that with Forth they could change anything. They didn’t spend large amounts of time caught in bugs they discovered in someone else’s compiler, or in elaborate work around schemes fighting with their software as they had before. If they wanted to change something they just did and moved on to other productive work. They didn’t get stuck like they often had before.
So armed with software that was smaller and simpler and easier than what they had before and with an interactive modular develop and debug methodology that was more effective in the integrated development environment they were happy. They were delighted to have seen improvements in their productivity as programmers, their understanding and their freedom to do what they wanted to do. They also turned off a lot of people who didn’t want to believe that these people could actually have all this stuff and made comments about how this was too good to be true so Forth must just be a religion or cult or something.
So far everyone has said, yes, yes, we all know this ancient history of Forth. So far everyone has been with me and mostly agreeing. So let’s get to the more controversial stuff.
I begin with this history because it is my opinion that this is as far as most people got before they headed back toward more conventional programming practices for various reasons. Little by little as people added their favorite features from their favorite languages to their Forth and fought to standardize the practice Forth became bigger and more complex. Bigger computers and growing libraries of code made it possible to easily compile bigger and bigger Forths.
When Forths were small and simple they didn’t take much source code. There weren’t too many words. Even on the slow systems of the old days a simple linked list of the name dictionary was sufficient to search things quickly. As systems became larger and larger dictionaries became more complex with wordlist trees and more complex methods of searching the more complex dictionaries were introduced which introduced more complexity. In an environment of spiraling complexity in the popular operating systems and GUI Forths expanded their interface to keep up. Now the glue between Forth and the user interface could be hundreds of times bigger and more complex than a complete Forth system in the old days.
Some of these Forth systems are advertised as having the best compilers that produce the fastest code. What they don’t tell you is that it may be true given that you are ready to accept a 90% or 99% slowdown to move into that environment in the first place. If you choose to mount your Forth under a GUI that takes 90% of the CPU power and leaves 10% for your Forth you may need that optimizing compiler even on a fast computer. We have ported the chip simulators to various compilers. We moved from a 16 bit DOS environment to a 32 bit Windows environment to get higher performance. When we hit the OS wall we still wanted more speedup so we ported back to the 16 bit DOS environment where we could get out from under the API load. We were able to speed up the program 1000x times by switching to a Forth that wasn’t crippled by its Windows interface. What is interesting is that the program runs 1000x faster in a Windows environment by ditching the Windows Forth. We have a strong incentive to replace the many megabytes of OS code with a couple of K of reasonable code to get the same functionality. We prefer programs that are 1000x smaller and 1000x faster and easier to write and maintain etc. If you are stuck in an excessively complex environment using Forth gets you out from under some of the complexity facing other people, but only a tiny bit of it.
Complexity demands more complexity. When the source code gets really big and complex it begins to demand things like version control utilities. Now between the huge files and time spent on version control jobs become too big for one person so we split them up and assign a team. Now we need a team of four. Now we need a more complex version control system with multiple user access. Now programmers are spending more time with the complexities of version control and other people’s bugs that four isn’t enough so we expand the team. Diminishing returns is the obvious result.
Many commercial and PD ANS Forth implementations Forth have become as complex as ‘C’, or extensions to ‘C’. The ANS standard went beyond the Forth core into extension libraries and it was common practice to start with everything from the last twenty years. We had Forths that were hundreds (or thousands) of times bigger and more complex than early Forths. They still supported the factoring, and the interactive nature of Forth development so they still had some the factors that made up that old 10x that we loved in the old days. But often now they were carrying megabytes of baggage and users were dealing with programs as large and complex as many other languages. Forth had changed so much that many systems require a full page or more of code to build a hello-world program thanks to the use of dreadful APIs.
There were traditional Forth programmers and new Forth programmers who could use these environments in a similar way to what they had once done but the common practice was to introduce coding style, layout, and libraries plucked right out of other languages. Common practice became very unForthlike and in particular beginners were often exposed to such examples in places like c.l.f. between the debates about who could write the wierdest code to break the outer fringes of the ANS Forth standard.
Chuck’s view of programming, as I understand his description of it, is that there is a problem, a programmer and his abstraction and the computer. Forth was there to let the picture be as simple as possible and let the programmer map the solution to the problem to the computer.
Problem --- Programmer with abstraction of problem --- Computer
and this leading to a solution that looks like this.
User --- Programmer's simple implementation by abstraction of the problem to the computer --- Computer
This was Chuck’s original idea of Forth even though in the old days the normal picture was not as complex and layered as it has become today. There were only a few layers between the programmer and the computer in those days but that was the problem that Forth was suppose to avoid. As the layers have become more numerous and deeper it has become even more important to let Forth avoid that problem.
As each of the layers of abstraction were added to the model and common practice over the years we were told that each would result in smaller, simpler programs because they would not need their own copy of things we standardized on. Programmers were suppose to become more productive and systems were suppose to become easier to understand and software would be easier to write, there would be more code reuse etc. Like cooking a frog in a pot the water the pot got hotter and hotter without people noticing who was coming to dinner until most of the problems most people face were introduced this way. People complain now that they spend more time looking for some code to reuse this way than they used to spend writing code when they used to do that. Chuck on the other hand has learned how to be more productive and write better code faster.
Chuck wants there to be nothing in his way. Chuck wants to make the computer simple and easily comprehended so that no extra layers of abstraction are needed to get at it or the problem. Chuck wants to make the solution simple so that it easy to write and efficient and has no extra layers of unneeded fat. Chuck seeks a simple efficient abstraction of the actual problem to the actual computer.
Chuck does not like the idea of a generalized OS providing a thick layer of abstraction that can introduce unneeded code, unneeded complexity, and inefficiency. He will support the idea of the abstraction of an OS but not one for everything. He and I would agree that in many environments there are layer upon layer of abstraction, that introduce complexity.
The people coming into computing in these times are being taught that the picture below is reality of a computer. They face enormous problems as a result. Almost no one gets to deal with the simple reality of the problem or the computer but must deal with the complexity of a thousand other people’s abstractions at all times.
Problem --- Programmers's abstractions of problem(s) --- Programmers's abstractions in software (example: OO w/ late binding) --- Programmers's abstractions of software reuse (general source libraries) --- Programmers's abstractions of optimizing compilers knowing more than they --- Programmers's abstractions of the computer GUI API --- Programmers's abstractions of the computer OS Services --- Programmers's abstractions of the computer BIOS --- Programmers's abstractions of the computer architecture ('C') --- Computer (too complex for all but a few humans to grasp)
These are two very different points of view. Chuck has said that he would like to Dispel the User Illusion. He means that the user has the illusion that all these layers of abstraction ARE the computer. If they could see beyond the illusion to see only the simple problem and were only faced with mapping it to a simple computer things stay simple and simple methods work. The majority of problems are avoided this way.
Those who have been working on making Forth more mainstream, extending it, and merging it with ‘C’ libraries and popular APIs have applied Forth in a very different way than Chuck. What made Forth popular twenty years ago was that Forth provided a simpler model and made programmers more productive because they weren’t trapped behind so many barriers introduced by other environments. They could do things the way that made the most sense not the way they had to be done.
Chuck originally created Forth to avoid problems introduced by unneeded abstractions. There was the abstraction of a Forth virtual machine and the expression of a solution in terms of that abstraction. Chuck has spent years simplifying and improving the virtual machine and has moved that abstraction into hardware to simplify both hardware and software design. He has a simpler virtual machine model, implemented in hardware on his machines, and a simple Forth environment implemented on top of it.
In many discussions that I read in c.l.f someone will ask how other people would accomplish such and such. My first thought is usually something about how it couldn’t be much simpler than what we do.
Acolor fontcolor !
to change the color of output in a numeric picture. What does it take? A store to memory, a few nanoseconds is the answer when you keep things clean. Other people will post tens of pages of detailed code that they need because of the bizarre behavior of particular layers of their layer upon layer of abstraction introduced problem laden environments.
People have said that without all this abstraction the general purpose OS could not run on innumerable combinations of cobbled together systems made of boards and cards and drivers from a thousand different vendors. This may be true although only in isolated cases will it sort of run anyway. It is also true that computers don’t have to be built that way. They can be built with logical, simple, inexpensive but high performance designs. The problem is that there is a cost to carrying around drivers for thousands of computers when in reality you are always only using one set. Neither hardware nor software have to be built that way. The problem is that the number of bugs and related problems or the amount of waste of resources can cripple the computer and/or the programmer.
With so many people using Forth today as a sort of scripting environment on top of every generalized service and abstraction as everyone else the common practice in Forth was no longer 10x compared to other ways of solving those same problems. Meanwhile I have been watching Chuck very closely. He seemed to still have a 10x up each sleeve that I saw very few other people using. He had a very different style of using Forth by continuing to explore in the direction he had been headed with Forth originally while most of the Forth community was going in the opposite direction. What are these other 10x factors?