Month: July 2010

  • LinkedList 33x schneller als ArrayList oder “Kenne deine API!”

    Für meine Arbeit schreibe ich zum Test gerade ein kleines Plugin für ImageJ, indem ich unter anderem einen Region-Fill Algorithmus brauche – leider tut’s der filler von ImageJ hier nicht – also schnell was selbst zusammengehackt:

    Startpunkt initialisieren und in eine Liste damit
    while (Liste nicht leer) {
       hole ersten Punkt P aus der Liste
       prüfe Eigenschaften von p.x/p.y auf dem Bild
       if (Eigenschaften erfüllt){
          füge der Liste die Punkte darüber, darunter, rechts und links hinzu
       }
    }
    

    Vorher eine ArrayList entsprechend groß initialisiert, damit die nicht dynamisch wachsen muss und gut ist’s.

    Moment – in vielen Iterationen werden hinten an der Liste 4 Punkte angefügt. Das geht mit der ArrayList schön schnell, wie man im ArrayList Quellcode unschwer erkennt (wenn die Liste groß genug ist). Aber in jeder Iteration wird vorne das erste Element entnommen. – Ein Blick in den ArrayList-Quellcode offenbart ein “System.arraycopy(elementData, index+1,  elementData, index, numMoved);“. Oha – das riecht eigentlich eher nach einer LinkedList.

    Also: Methode profilen, Listentyp ändern, nochmal profilen (mit dem NetBeans Profiler ja kein Thema). Ergebnis: LinkedList ist wie erwartet viel schneller. Ohne meinen ganzen sonstigen Code reduziert sich der Testfall in etwa auf folgende Testklasse:

    public class ListTest {
    
        public static void main(String[] args) {
            List al = new ArrayList(31000);
            List ll = new LinkedList();
            long a = System.currentTimeMillis();
            testWith(al);
            long b = System.currentTimeMillis();
            testWith(ll);
            long c = System.currentTimeMillis();
    
            System.out.println("ArrayList: "+(b - a) + " ms");
            System.out.println("LinkedList: "+(c - b) + " ms");
        }
    
        private static void testWith(List list) {
            list.add(new Point(0, 0));
            int i = 10000;
            Point p;
            while (!list.isEmpty()) {
                p = list.remove(0);
                if (i-- > 0) {
                    list.add(new Point(p.x, p.y - 1));
                    list.add(new Point(p.x - 1, p.y));
                    list.add(new Point(p.x + 1, p.y));
                    list.add(new Point(p.x, p.y + 1));
                }
            }
        }
    }
    

    Das Speedstepping am Notebook nicht vergessen, sonst fährt die CPU am anfang ja noch nicht auf Vollgas und schon rennt der Test. Die ArrayList habe ich auch extra noch mit mehr Elementen initialisiert, als jemals reinkommen. Ausserdem geht die Initialisierung auch nicht in die Messung ein (ist im Vergeich mit dem Rest zwar eh vernachlässigbar klein, aber damit niemand auf die Idee kommt, der Vergleich wäre unfair …).

    Ausgabe:
    ArrayList: 860 ms  = 100%
    LinkedList: 31 ms  = 3,6%

    Sieht man sich die API und den Quellcode der beiden Klassen an, verwundert das Ergebnis nicht wirklich. Der unterschied skaliert natürlich auch mit der Anzahl der Iterationen.

    Fazit

    Ist ArrayList also schlecht? – Klares NEIN! Nur für genau diesen Anwendungfall (vielfaches Einfügen am Ende, vielfaches Herausnehmen am Anfang, kein Zugriff auf Elemente irgendwo dazwischen nötig) ist die ArrayList der Speicherstruktur der LinkedList einfach unterlegen, die genau auf diesen Punkten optimal funktioniert.

    Ergo: Know your API! Man sollte sein Handwerkszeug kennen und nicht blindlings einfach das verwenden was man sonnst auch immer nimmt und hoffen, dass Java ein allmächtiges Werkzeug ist, das einem alle Arbeit abnimmt (und dann nacher groß jammern, dass in C++ ja eh alles viel schneller geht). Und wenn man Zweifel hat, ruhig mal einen Blick in den Sourcecode werfen und ausprobieren ;-)

  • Impact of Flash SSDs on Spatial Indexing

    Neben Paros war ich auf der SigMod 2010 auch mit einer Veröffentlichung auf dem DaMoN Workshop (Data Management On new Hardware) vertreten. Der Titel der Veröffentlichung war “On the Impact of Flash SSDs on Spatial Indexing“.

    Dass SSDs schnell und cool sind, ist ja mittlerweile allseits bekannt. Leider sind sie noch etwas teuer – nichts desto trotz haben sie den unglaublichen Vorteil, dass die Zugriffszeiten bei wahlfreien Lesezugriffen deutlich kleiner sind, da sie nahezu keine Seek-Zeiten aufweisen (also die Zeit in der der Lesearm der regulären Festplatte erst zur richtigen Position gefahren werden muss, bevor gelesen oder geschrieben werden kann). Diese Seek-Zeiten sind gerade bei Datenbankindices einer der bremsenden Faktoren. Da unser Lehrstuhl auf Datenbanken, DataMining und Indexing spezialisiert ist, haben wir uns daher angesehen, wie sich der R*-Baum (einer der Standard-Indices für mehrdimensionale Daten) auf SSDs im Vergleich zu HDDs verhält. Insbesondere, wie die Indices skalieren und wie es mit der Performanz aussieht, wenn höher dimensionale Daten ( > 10 Dimensionen bzw. Spalten) mit einem R*-Baum indexiert werden sollen und wie es sich mit dem Fluch der Dimensionalität verhält.

    Fazit: War eine doch recht spannende und vor allem recht praktische Arbeit , da wir nicht einfach nur Modelle durchrechnen wollten, sondern wirklich die Zugriffe auf die Platte sehen und messen wollten – was die Tests auch sehr zeitaufwändig gemacht hat, da Ram und Platte eben doch einen “kleinen” Geschwindigkeitsunterschied haben.

    Abstract:

    Similarity queries are an important query type in multimedia databases. To implement these types of queries, database systems often use spatial index structures like the R*-Tree. However, the majority of performance evaluations for spatial index structures rely on a conventional background storage layer based on conventional hard drives. Since newer devices like solid-state-disks (SSD) have a completely different performance characteristic, it is an interesting question how far existing index structures proft from these modern storage devices. In this paper, we therefore examine the performance behaviour of the R*-Tree on an SSD compared to a conventional hard drive. Testing various in uencing factors like system load, dimensionality and page size of the index our evaluation leads to interesting insights into the performance of spatial index structures on modern background storage layers.

    Die Veröffentlichung kann man auf unserer Website herunterladen: On the Impact of Flash SSDs on Spatial Indexing

  • Java Memory Model / MultiThreading in Java

    Wer sich für das Java Memory Model und insbesondere für Multi Threaded Code und die Probleme mit denen man sich konfrontiert sieht, wenn man multi threaded programmiert interessiert, könnte das Video durchaus interessant finden.

    Titel: Advance Topics in Programming Language: Java Memory Model
    von Jeremy Manson

    [youtube=http://www.youtube.com/watch?v=1FX4zco0ziY]