Mittwoch, 15. September 2010

Neuer Indizierungsalgorithmus

Die Produkte von scireum zeichnen sich durch eine exzellente Suchqualität und Suchperformance aus. Dafür bauen wir auch in SellSite pro Shop einen speziellen Suchindex auf. Hierbei müssen natürlich alle Artikel des Shops aus der Datenbank geladen und verarbeitet werden.

Nun zu unserem Problem. Obwohl wir bereits einen optimierten Tiefendurchlauf (durch die Produktgruppen) implementiert haben, wurde der Java-Heap währen dem Indizieren größer und größer. Bei 50.000 Artikeln waren da schnell 1,5 GB Speicher verbraucht. Etwas Profiling mit Visual VM brachte die Erkenntnis: Die von uns verwendete JPA-Bibliothek EclipseLink von Oracle speichert alle Objekte die "Lazy" nachgeladen werden in einer "Unit of Work". Das bedeutet in unserem Fall: Die vollständigen Artikeldaten.

Die Lösung brachte ein einfacher Trick: Jedes Produkt wird in einer eigenen "Unit of Work" vollständig vorbefüllt. Dadurch muss das "Lazy-Loading" von EclipseLink keine Daten nachladen und der Garbage-Collector kann die verarbeiteten Produktdaten sehr schnell wieder freigeben. Das Ergebnis: 50.000 Artikel verbrauchen weniger als 200 MB Heap. Zusätzlich läuft der Prozess nun 30% schneller, da der Heap weniger ausgelastet wird:

Hier die Speicherauslastung mit dem ursprünglichen Algorithmus. Deutlich zu erkennen: Nach der Indizierung, wird die "Unit of Work" abgeschlossen und eine große Menge Speicher freigegeben:




Der neue Algorithmus zeigt das übliche Sägezahnmuster einer "gesunden" VM:

Die 30% Performance-Gewinn sind auf den Garbage-Collector zurückzuführen. Dieser hatte beim ursprünglichen Ansatz einiges zu tun:

Mit dem neuen Algorithmus kann SellSite nun auch wesentlich größere Datenmengen performant und stabil verarbeiten. Die Suche selbst kann ja "von Haus aus" (sprich: CatalogPortalSystem) problemlos mehrere Millionen Artikel im Millisekundenbereich durchsuchen.

Keine Kommentare:

Kommentar veröffentlichen