If you are following this blog you are aware that I’ve been investigating options for hosting Smalltalk in the cloud. One very successful hosting solution for a number of languages is Heroku. Not only do they support a number of languages built-in, but they also allow anyone to create a buildpack to support another language or framework. So, what would it take to add Smalltalk to Heroku? First, we need to acknowledge that Will Leinweber has a buildpack for Redline Smalltalk. Since Redline Smalltalk is based on the Java VM, this is more about running Java on Heroku than Smalltalk (which is not to minimize the accomplishment, just to note that getting a Smalltalk VM running is not quite the same).
The next thing to note is that running an application in the cloud might be different from running it on your own server. The model most hosting providers follow is that they package your application into a stand-alone directory tree that is saved on their server. When you ask for one or more instance(s) to run they copy the directory tree onto an available machine, set some environment variables (including a port on which to listen for HTTP requests), execute an application launch command, and then route requests to the port. Horizontal scaling is accomplished by starting additional instances and routing requests to them in some fashion. If an application dies then the hosting provider cleanup the directory and repeat the process with a new directory. Thus, each instance is isolated from other instances (even of the same application), and the file system is “ephemeral” and exists only while the instance is running. From a Smalltalk perspective, this means that typical image-based persistence is not trivial. I have some ideas on how this might be addressed, but need to get Smalltalk into the environment first.
As mentioned above, you can create a third-party buildpack that packages and starts your application. The buildpack is essentially three bash scripts that (1) report whether it can handle a particular application (“Do I have everything here that I need?”), (2) transform the application into its runtime structure, and (3) tell the framework how to start instances of the application. This is all fairly straightforward and has been done for many languages and frameworks. Note, however, that a “buildpack is responsible for building a complete working runtime environment around the app. This may include language VMs and other runtime dependencies that are needed by the app.” So, to get something like Pharo running on Heroku we need a Cog VM that runs on the Heroku server.
To find out more about the Heroku environment I decided to try it out. First, I signed up for a free account at https://id.heroku.com/signup and then install the tools. At this point I followed the simple instructions to create a “Hello, world” application:
mkdir ~/cloud/heroku cd ~/cloud/heroku heroku login git clone git://github.com/heroku/ruby-sample.git cd ruby-sample heroku create git push heroku master heroku apps:rename mygreatapp heroku open
This opened a web browser on http://mygreatapp.herokuapp.com/ and the expected page was displayed. The next thing that is rather nice is that you can run a non-web application on the Heroku server and have stdin/stdout/stderr routed back to your client shell:
heroku run bash
This starts a bash shell on the server; just as if you used ssh! Now we can do some things to investigate the server environment (this script represents what came at the end after I tried various things described next):
uname -m -o # x86_64 GNU/Linux ll /lib/libc.so* # 2.11.1 cat /proc/version # Linux version 3.8.11-ec2 (gcc version 4.4.3) file /sbin/init # ELF 64-bit LSB, for GNU/Linux 2.6.15 cat /proc/cpuinfo # Intel(R) Xeon(R) 4 CPUs X5550 @ 2.67 GHz curl --version # 7.19.7 tar --version # 1.22 zip --version # command not found
The shows us that heroku is running 64-bit linux on Xeon processors. Since we have non-root access we can’t do much to changes these characteristics. We can, however try installing Pharo and see what happens. My first attempt was to download a one-click but that was a zip file that couldn’t be unzipped. Next, I got a recent Cog VM that came as a .tgz file. I uncompressed this with tar and tried to run it. This gave the error “/usr/bin/ldd didn’t produce any output and the system is 64 bit. You may need to (re)install the 32-bit libraries.” So we can’t run the 32-bit application–at least not without some work. Next I tried a 64-bit Squeak VM and uncompressed that. With this we got further, but now have the error “squeakvm64: /lib/libc.so.6: version `GLIBC_2.14′ not found (required by squeakvm64).” Note above that the Heroku server has GCC 2.11 (from 2009), so executables compiled with later libraries will not run.
I guess that the correct thing to do is to build the needed binaries on the Heroku server (as described here). Presumably this would guarantee that everything works together. Before trying to build Cog I might look at GNU Smalltalk.
Before finishing up we need to stop our Heroku application so we don’t use up resources. Exit from the bash shell on the server (if it hasn’t timed you out!), and then destroy your app:
heroku apps:destroy mygreatapp
In any case, I’ve learned enough for today and will try some other things next week (probably non-Heroku things!).