22 de febrero de 2017

Trying Chez Scheme

A new virtual machine for Racket

The plan is to replace the Racket virtual machine with Chez Scheme, including the interpreter and the JIT and everything else, within a year. There are still many unknowns and details to be solved. In particular, I'm interested in how Chez optimizations are compared to the optimizations Racket currently has. Moreover, there are a million small incompatibilities between Chez and Racket that must be fixed in the middle layer and they will directly or indirectly affect the optimizations.

The problem is that in order to understand what is going on, I need to break^H^H^H^H^H make modifications and maybe try to make improvements to the current optimizations in Chez, and see if the changes that I try are correct or they produce errors. So the first step is to compile Chez and take a look at the tests.


Compiling Chez on Windows

I can compile it, but I still have errors in the tests. I guess I have something misconfigured on my machine. I'm still fighting against iconv.dll. And also there is probably some other problem because there are too many tests that fail. Let's forget Windows for now.


Compiling Chez on Linux

Compiling on Linux was easier than I expected. Almost no surprises. Foolproof instructions for installing on a virtual machine:


  • Download and install VirtualBox
  • Download the Ubuntu disk (desktop)
  • Install Ubuntu on the virtual machine (not on the real machine). The only hard question is the size of the hard drive, I put 12GB and that is enough. I recommend turning off the option to lock the screen after 5 minutes of inactivity because several of the following steps take a long time.

The following steps are explained in the BUILDING file. But in case of doubt the recipe is:

sudo apt-get install git
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo apt-get install libx11-dev
git clone https://github.com/cisco/ChezScheme.git
cd ChezScheme
./configure
sudo make install
make test
cat a6le/mats/summary

The make test step performs a lot of tests and it takes about an hour, so you have to be patient. The errors will be shown at a6le/mats/summary and if there are no errors the file should be something like

-------- o = 0 --------
-------- o = 3 --------
[...]
-------- o = 3 ehc=t eval=interpret --------

Where each line represents a possible configuration of the tests. In my case it was a success (almost) at the first attempt.


Automatic tests in Travis

For the tests in Travis I wanted that in case of an error that the program finish with an error code other than 0, for Travis to notice it and signal the fault.

In addition, I wanted to be able to run each of the test configurations separately, so they can run in parallel in Travis. This also helps to identify where the error is.

One of the problems is that some of the variables of the makefile are reused.

o : In some makefiles it is obviously the extension of the files with object code, that is o=.o or o=.obj according to the compiler. In others makefiles it is obviously the level of optimization, typically o=0 or o=3.

cp0 : In some makefiles it is the number of times the step cp0 that performs the optimizations of the Chez code is applied, and in others it takes the values t or f to indicate whether the step cp0 is applied or not. (Maybe it’s possible to change the t/f by 0/1 (or 0/3) and use the same meaning everywhere?)

I solved it by creating two new variables one_o and one_cp0 that at some point are copied to the original variables, taking some care to handle the case where they are not defined.

To the main makefile I added an option to run all the tests with a given configuration instead of all the tests with all the configurations. For example:

make testone one_o=3 one_cp0=t

The changes in the makefiles are not very elegant, moreover, they are probably a monstrosity, but they run in my machine (be careful with the tabs):

makefiles/Makefile.in
testone:
(cd $(workarea) && $(MAKE) testone PREFIX=$(workarea)/)

makefiles/Makefile-workarea.in
ifdef one_o
  new_o = o=$(one_o)
else
  new_o = 
endif
ifdef one_cp0
  new_cp0 = cp0=$(one_cp0)
else
  new_cp0 = 
endif

testone: build

(cd mats ; $(MAKE) allxonewerror $(new_o) $(new_cp0))
@echo "test run complete.  check $(PREFIX)mats/summary for errors."

/mats/Mf-base
allxonewerror: prettyclean
$(MAKE) allxhelp
$(MAKE) maybe-raise-error

maybe-raise-error:

if [ "`wc -l < report-${conf}`" != "0"  ] ; then\
 $(MAKE) raise-error ;\
fi

raise-error:

$(error We found an error)

The .travis.yml file is more or less standard. Instead of make install I use make build to avoid using sudo, so Travis runs the tests almost immediately instead of waiting for amachine with sudo enabled. My version still generates a small complaint because build uses internally sudo or something like that, but it does not seem to be important for the final result.

.travis.yml
sudo: false
language: c

matrix:

  include:
  - os: linux
    compiler: gcc
    env: CHEZ_TEST_ARGS="one_o=0"
  - os: linux
    compiler: gcc
    env: CHEZ_TEST_ARGS="one_o=3"
#[…]
  - os: linux
    compiler: gcc
    env: CHEZ_TEST_ARGS="one_o=3 eval=interpret ehc=t rmg=2"

script:

- ./configure
- make build
- make testone $CHEZ_TEST_ARGS

The code is available in github (tests ), along with an additional change that adds an obviously wrong test just to see that when there is an error it is detected (test ). 


Some ideas

My plan is to analyze the Chez code now, but there are some improvements that I think I will ignore for now.

I would like instead of running all tests for each option with make testone, being able to run each test separately, so the output in Travis is shorter and easier to understand and it is easier to find the error.

And I would like to try to fix the compilation in Windows and if possible add the tests in AppVeyor.