Monthly Archives: August 2012

ESUG 2012: when the time to pay for the beers has arrived!

Hi guys. In a blog post of last year, I said:

“What is really great is to meet people. Have you ever sent 1 million emails to someone without even knowing his face?. Is he 70 years old? 20 ? What language does he speak?  Well, ESUG is the perfect conference to meet people by real, face to face. The best part of ESUG happens in the “corridors”, I mean, talking with people between talks, after the conference, in the social event, etc. There will be people who will ask you about your stuff, they will give you feedback and ideas. You will find yourself wanting to give feedback to others. It is a nice circle.”

This year, we should have another motivation. How many times have you promised people to buy them a beer if they did XXX? How many times people have promised you a beer for doing YYY? What better place than Belgium to balance the accounts?

I have already done my homework. I own beers to: Alain Plantec and  Henrik Sperre Johansen.

Anyway guys, hope to see you there!

Advertisements

Tanker screencast and image ready for testing

Hi guys. Last days, we submitted Tanker to the ESUG Innovation Technology Awards. As part of that submission, I have created a screencast and an image with the examples.

The screencast gives you an introduction to Tanker and shows you how to export and import packages. I starts with a simple example, then it exports a real library and ends up exporting all Seaside, Magritte and Pier 🙂   Ahhh yes, sorry for my voice, I know it is ugly hahaha. You can also watch it here:

You can also get the image I used for the screencast, which you can try and experiment.

Have fun,


Tanker: transporting packages with Fuel

Hi all. You may have noticed that Tanker is starting to appear in some mails or in the Pharo issue tracker. Tanker is a project that Martin and I have been developing for a while and we are going to submit it this year to ESUG Innovation Technology Award. Therefore, I thought it would be interesting to explaining what it is, its current status, its goals, etc.

What is “Tanker” and what was “FuelPackageLoader”?

Right now the common way to export and import packages in Pharo is by using Monticello (or doing fileOut, which is almost the same). This ends up exporting the source code and then compiling it during the import. Tanker is a tool to export and import packages of code in a binary way using Fuel serializer. Using Fuel enables us to avoid having to compile from sources during the import. Tanker understands the concept of “packages of code” and the correct integration of them into the system. For example, it initializes classes, sends notifications, etc.

Tanker was first a prototype called “FuelPackageLoader” which was what I used for the example of exporting and importing seaside packages. In the last months, we have renamed the project to “Tanker”. Why? Because we do not want people to think that it is a Fuel project. In fact, Tanker is a simple USER of Fuel. Just as any other code that uses Fuel. This is why we have also moved it to its own repository.

Fuel has a package called “FuelMetalevel”. This package gives Fuel the knowledge of how to correctly serialize and materialize classes, metaclasses, traits, method dictionaries, compiled methods and closures, in other words, all the entities related to code and runtime infrastructure. It only knows how to serialize and materialize correctly. Nothing else. It does not initialize classes, it does not notify the system about the materialized classes, it does not install classes in Smalltalk globals, etc.

Current features, design and missing things

Right now, Tanker provides the following features:

  • It is able to export a package to a .tank file and import it in another image. The input for the export is a TAPackage which basically contains a list of classes and a list of extension methods. We are completely decoupled from the “package representation” (PackageInfo, RPackage, MCPackage, etc). However, we provide an API if you want to directly export from those types of packages.
  • Classes are initialized and installed in Smalltalk globals, events are sent, etc.
  • It has the ability to add additional user-defined objects to the package being exported (this is used, for example, for the Pharo generation from a kernel to store large/heavy class variables, tables and fonts).
  • It supports pre and post load actions represented as closures.

From the design point of view, Tanker:

  • Fully serializes classes and traits (not its “definitions”)
  • Does not use the ClassBuilder during materialization. Tanker itself materializes the “class objects” and sets the data.

So far, we are missing:

  • The possibility to export source code (right now classes and methods do not have source code) and also to install it in the .changes file during import.
  • Some validations during import. For example, the superclass of a class being installed may have changed its shape and, therefore, the classes to install need recompilation (because the bytecodes accessing instVars offset may be shifted or wrong). Or if a class already exists in the image and the shape has changed, we need to update the existing instances.
  • Integration with other tools like Monticello and Metacello.

Results with the “current status”

There are so far 3 real examples of Tanker:

How to install it and use it

Tanker will work only in the bleeding edge of Pharo 2.0. So I first recommend you to get an image from Jenkins. Then, you can install Tanker this way:

Gofer it
 url: 'http://smalltalkhub.com/mc/marianopeck/Tanker/main';
 package: 'ConfigurationOfTanker';
load.
(Smalltalk at: #ConfigurationOfTanker) load.

To export a package and provide yourself the classes and extension methods, you can:

| aPackage aStream |
"Export"
aStream := 'demo.tank' asFileReference writeStream binary.
aPackage := TAPackage behaviors: {TestCase. TestLocalVariable. } extensionMethods: #().
TAPackageStore new storePackage: aPackage on: aStream.

"Import"
aStream := 'demo.tank' asFileReference readStream binary.
TAPackageLoader new loadFrom: aStream.

Then you can also use the API that provides helper methods to RPackage and PackageInfo:

aPackage := TAPackage fromPackageInfoNamed: 'MyPackage'

You also have #fromPackagesInfoNames:, #fromRPackageNamed: and #fromRPackagesNames:. Of course, there are more use-cases, API and scenarios. But, so far, that is the simplest usage. For more examples, browse the class side methods of TankerExamples.

GSoC and “new status”

The results so far are quite promising and not anymore a “proof of concept”. However, we still need to support source code management as well as the already mentioned pending features. Because of this reason, Martin submitted Tanker for the GSoC and fortunately it was accepted. So, right now we are moving to a different design to solve the requirements.  The idea now is NOT to serialize classes and traits, but instead serialize their “definition”. Imagine by “definition” the string used to create them. Then, during import, instead of just materializing class objects, we take the definition and, using the ClassBuilder or similar, we “evaluate” the definitions and we get the new classes.

At the same time, the idea is to export the source code of a package in a file (myPackage.tank.st or something like that) and the binary representation in another file (say myPackage.tank). Then, during import, you should be able to import with or without sources.

Side-effect projects of Tanker

You may be wondering why we didn’t start from the very beginning with the “definitions” way. Well, to be honest, the ClassBuilder is a mess, difficult to understand, maintain and extend. It was really hard trying to use it for our purpose. So the first “side-effect project” of Tanker is to continue pushing the “new ClassBuilder” started by Toon Verwaest based in “slots”. Martin Dias, Guillermo Polito and Camillo Bruni are pushing it and writing tests. I think it could be soon integrated in Pharo and replace the old one. The idea is that Tanker will use this ClassBuilder, for example, to evaluate the definitions.

When we are importing a class, it may happen that the superclass (present in the image where we are importing) has changed its shape (added or removed instVars, change supperclass, etc). If this is true, we have to recompile because the bytecodes accessing intsVars will be a shifted offset. However, recompiling is slow and we don’t want that. Therefore, Tanker will use IR (intermediate representation) which was developed by Marcus Denker and the team working with the new Opal compiler. IR is just a nice model generated from a CompiledMethod. The idea is that we can generate the IR, modify it (bytecodes for instVars accessing, for example) using this nice abstraction and API and then generate back a new CompiledMethod. This is way faster than recompiling. Furthermore, IR is decoupled from Opal so we don’t need whole Opal.

Conclusion

Tanker started as an experiment to see whether Fuel coud be used to export and import packages in a binary way. The proof of concept was quite good so we are now going forward with the source code management and related stuff. It is important to notice that Tanker just “uses” Fuel. Fuel is completely decoupled from Tanker. We think Fuel was well received by the community. We are doing our best so that Tanker gets positive feedback as well.