The Martian Chronicles

A fast table for Pharo

Why we need yet another list?

In Pharo, we have several competing list implementations since day one. But all those implementations depend on one unique original: LazyListMorph. While this is hidden in the most used hierarchy: PluggableListMorph and children, at the end this is what we always have, if we want to use lists in our GUI. The original design worked fine in the use cases they have at the time, but it started to show age very fast (in fact, LazyListMorph is not the first list morph written, it is itself an attempt to solve performance issues).

What were the problems? Well, a short but important list:

  1. List morph does not allow larger lists to be shown performantly. Since it keeps all elements as morphs in a huge collection, it starts to lag after some hundreds.
  2. List morph does not handle very well complex element morphs. While it works fine with string morphs, if we want to use other kind of morphs as list elements (like for example, to show icons, etc.), list morph also lags very fast.

Along with this two fundamental problems, there were some others: since the original was intended to show lists, if you want to do a table, you can't. Now, you can say a list is a particular case of a table (it is a table with just one column, after all), but the other way (a "multi-column" list) is not so easy to implement. But it was done (MulticolumnLazyListMorph and PluggableMultiColumnListMorph) and during some years that was the unique solution we had.

Other attempts have been made to solve the performance issues of this implementation, like the NewList, but it's design is based on spawning threads to fill the elements array and it never worked really fine.

A new implementation

So, I started to write a new list for Pharo during an insomnia night, trying to solve this problem (And honestly, really tired of seeing how the current IDE feels slow –and makes Pharo itself feels slow– when there is no real reason to it).

For me, three conditions need to be fulfilled:

  1. It has to allow large number of rows (infinite if possible) and it has to be fast!
  2. It has to encourage extension (like for example to make editable fields)
  3. It has work for display tables, lists and with time, also trees

Since I know some implementations outside the Pharo world, I reviewed a couple and I decided to take as inspiration the implementation of Cocoa. This is a really simple design, who is proven to work very well:

  1. The main component is a table, and a list is considered just a table with one unique column
  2. It uses a data source (a data model) to provide elements to the list
  3. You can provide any view element as a cell
  4. Implementation demands only the elements to be shown. So you can have infinite elements and not instantiate them unless you will show them.

It looked fine, and after some hours of work, I finished a first version.

Comparing with older implementation

In general, all my benchmarks gave me a 10x increment in the speed of rendering.

And of course, showing thousands of elements cannot be compared because it was simply not possible before.

Using fast table

Fast table is integrated in Pharo 5.0, and it will replace all older list usages. You can check some examples of it browsing class side of FTExample class.

Here, a small example on the easiest way to use it:

FTEasyListMorph new
    extent: 300@550;
    elements: Morph methods;
    icon: [ :method | (FTExampleMethodModel method: method) actionOn: nil ];
    display: [ :method | method selector ];		
    openInWindow.

Screenshot-easylist
Enjoy!

EDIT: I forget to say that I also made Glamour renderers for lists and tables. They are incomplete, but you can start play with them.

To install it, just execute this:

 Gofer it 
    smalltalkhubUser: 'estebanlm' project: 'FastTable';
    package: 'Glamour-FastTable';
    load.

... and you will have #fastList and #fastTable presentations.

Posted by Esteban at 2 July 2015, 10:05 am with tags pharo link

Leave your comment