About half a year ago, I added some tests which deploy various demos shipped with Factor, then ensure that the resulting binary is below a certain size. These tests always seem to start failing after I make major changes to the Factor core or compiler, because suddenly programs start pulling in code more than they should. It is certainly frustrating when I add a new language feature, debug it, then realize that all the tests pass except the deploy tests pass. Getting them to pass again sometimes involves a fair bit of effort, because I have to think of new tricks to reduce the image size again, and I'm pretty anal about not cheating and just changing the size limits in the tests. This is because it is a very satisfying feeling once I figure out a new trick, and the tests pass again.
For example, I just added optional type declarations to tuple slots, and rewrite a large portion of the low-level tuple class machinery. As usual, the deployed images blew up. My tool for figuring out how to reduce image size is Factor's low-level debugger, which can give a dump of the heap, find references to objects, and dump objects.
I started by moving
float-arraysand the inspector out of the core, so that they won't get loaded by default. This wasn't enough, however. The next step was having the tree shaker prune some word properties which were only used when loading new code, and not at runtime. Then, I noticed that there were a lot of duplicate, immutable byte arrays in the heap. This is the relocation info generated by the compiler to tell the VM about dependencies between code blocks, code GC information, and so on. Turns out that for a lot of different code blocks, the generated relocation info was the same. Replacing duplicate relocation blocks with references to the same object as the last stage in the tree shaker was enough to make the tests pass again. I also applied the same optimization to quotations and strings for good measure. After all these changes, the resulting reduction in deployed image sizes was so drastic that I went ahead and changed the deploy tests to tighten the size bounds even further -- I guess I'm just masochistic like that.
The deployed application sizes are pretty large compared to languages such as C and C++, however they're certainly much smaller than the dynamic language competition. The Tetris demo tree-shakes down to 1Mb; a console "hello world" is 340Kb; a GUI "hello world" is also around 1Mb; and the "bunny" demo, which downloads a 3d model via HTTP and renders it with OpenGL, tree-shakes down to 2Mb. In addition to the tree-shaken image, the only other dependency is the Factor VM (<200Kb), and on Mac OS X and Windows, the FreeType library (this dependency will go away at some point in the future). Furthermore, you get a nice double-clickable
.appon Mac OS X so that the user is not even aware they're running something written in Factor; it feels like any other native executable.
I believe the ability to deploy small, stand-alone binaries which do not contain any source code and do not depend on an external runtime environment is an essential capability for a general-purpose language. This is also something that many other language environments do poorly; Java requires you to bundle a large (at least 8mb) runtime environment, Python and Ruby have no way of distributing code without the source, and the free Lisp environments can usually save customized images but don't attempt to strip them down in any way, leaving you with a 25Mb "Hello World".
Factor has a lot of great features: an interactive development environment, stand-alone application deployment, the web framework, SSL, database libraries, Unicode 5.1, XML, etc, not to mention automated binary builds with continuous testing on 11 platforms. We've come a long way in less than 5 years, and I believe this is all thanks to the incredible productivity offered by the Factor language itself. This pace of development is not going to let up any time soon, and all the people who ridiculed "yet another programming language" in Factor's early days are only going to look more and more foolish as time goes on.