Grundsätzlich brauch man sich keine Gedanken machen den Cache zu leeren. Denn der Cache läuft im Hintergrund und optimiert dabei die Query-Geschwindigkeiten.
Daher ist in erster Linie ein Abschalten kontra-produktiv. Allerdings benötigt man für Benchmarks saubere Ergebnisse. Ohne weiteres ist dies in Neo4j leider nicht möglich. Neo4j
nutzt den System-Cache und lässt sich nicht überzeugen dem System anzuweisen den Cache zu leeren. Das ist schade, weil die enorm Ergebnisse verfälscht. Hier zeige ich euch 2 Möglichkeiten den
Cache zu leeren.
Ausgangs-Zustand
Bevor ich den Cache cleare bzw. die Wege dazu aufzeige, möchte ich erst einmal zeigen, wie viel Speicher das System hat. Damit können wir dann u.a. kontrollieren
ob unsere Maßnahmen geholfen haben.
Ich gehe davon aus, dass ihr Neo4j nicht als Service/Deamon installiert habt, es also immer von Hand startet. Ich setze voraus, dass das System neugestartet wurde und sonst nichts ausgeführt
wurde. Nun geben wir free ein und schauen die aktuelle Speicherbelegung an.
Das System hat also maximal 30 GB RAM und derzeit werden ~350 MB genutzt. Jetzt starten wir Neo4j mit /var/lib/neo4j/bin/neo4j start und schauen danach wieder
die Speicherbelegung mit free an.
Neo4j verbraucht somit allein nach dem Start ~20 GB.
Caching als Problem für Benchmarks
Nun ist so, dass Neo4j selbst nach einem Neustart bzw. Abschlante der Server den Cache nicht löscht, weil er eben zum System gehört. Für einen Benchmark ist
jedoch ein System von Nöten, welches verlässliche Antwortzeiten zurückliefert und nicht schon durch vorherige Suchen den Cache optimiert hat. Schauen wir uns ein paar Beispiele an was Caching
unter Neo4j für Auswirkungen hat
Da ich in der Cloud derzeit eine Instanz mit indexiertem Lucene Index am Laufen habe, nehmen wir einfach die Zeit für eine einfache Lucene-Suche. Geht dazu in die Neo4j-Shell mit
/var/lib/neo4j/bin/neo4j-shell und führt START n=node:titles("title:machine") RETURN count(*); aus. (natürlich habt ihr nicht meine Daten und müsst den Befehl
bei euch anpassen wenn ihr das nachstellen wollt). Führen wir die gleiche Suche einfach drei-mal hintereinander aus.
Nun ist unschwer zu erkennen, dass ab der 2. Query eine sehr gute Zeit erzielt wird. Damit ihr sehen könnt, dass dies kein Einzelfall ist, hier
auch nochmal an einer abgeänderten Suche gezeigt mit START n=node:titles("title:panel") RETURN count(*);.
Hier verhält sich dies identisch. Das Problem dabei ist nun, dass wenn bei späteren Benchmarks ähnliche Suchwörter genutzt werden, Neo4j natürlich schon etliche gepuffert hat. Da später dies
jedoch kein Real-Fall ist, wo Nutzer immer das Gleiche suchen, muss das Caching folglich verhindert werden. Oder es die Möglichkeit bestehen den Cache auf Knopfdruck zu leeren.
Neo4j kann dies von Hause aus nicht. Schauen wir hier abschließend noch einmal mit free auf den verwendeten Memory nach den Querys.
Methoden den Cache zu löschen
Wie ich schon erwähnt habe ist es mit einem Neustart von Neo4j-Server nicht getan. Das Caching erfolgt bei Neo4j System-weit.
Methode 1: System-Neustart
Die einfachste Methode ist einfach das System neu zu starten mit sudo reboot. Wenn wir nach dem Neustart wieder free ansehen, erkennen wir, dass wir quasi kaum
Speicherbelegung mehr haben.
Um zu zeigen, dass die Suche nun wieder die Ausgangs-Geschindigkeit hat, einfach die Neo4j-Shell öffnen und START n=node:titles("title:machine") RETURN count(*);
eingeben.
Auch wieder der Blick danach auf den Memory mit free.
Diese Methode hat jedoch den Haken, dass alle Verbindungen abbrechen zur Cloud-Instanz. Auch verliert man hierbei sehr viel Zeit und dabei meine ich nicht nur das Wiederverbindung sondern vor
allem der Neustart an sich und man start wieder unnötig im Root-Verzeichnis.
Methode 2: Cache purging
Um sonstiges Einflüsse zu vermeiden starten wir das System neu, damit wir wirklich sicherstellen ein frisches System zu haben. Danach dann wieder Neo4j starten und START
n=node:titles("title:machine") RETURN count(*); in die Shell damit der Cache gut gefüllt ist. Kurz nochmal mit free den Memory checken.
Um weiter fortzufahren muss jedoch Neo4j gestoppt werden. Also /var/lib/neo4j/bin/neo4j stop ausführen und nochmal free checken.
Jetzt purgen wir den Cache. Das ist sehr einfach, sofern man den Befehl kennt. Wir brauchen dazu nur die folgende Anweisung sync && echo 3 > /proc/sys/vm/drop_caches und danach dann nochmal mit free checken. Die 3 steht dabei für ein Parameter wobei alles geleert wird (free pagecache, dentries and inodes). Das sync vorher ist anscheinend wichtig, damit das System kurz nochmal den Speicher bereinigen kann. Ihr könntet übrigens auch echo 3 | sudo tee /proc/sys/vm/drop_caches nutzen, was das Gleiche ist.
Der Speicher ist also wieder frei. Auch jetzt testen wir wieder ob die Anfrage ähnliche lange dauert in der Neo4j-Shell mit START n=node:titles("title:machine") RETURN count(*);.
Un ein letztes mal nochmal free.
Fazit
Zugegebenermaßen ist das hier gezeigte ziemlich nervig, leider aber notwendig. Schade, dass Neo4j versucht zu tricksen und bei einem Neustart den Cache nicht zurücksetzt. Da fällt mir wieder der
Spruch ein, traue keinem Benchmark, den du nicht selbst gefälschst hast. Ich hoffe es bringt euch ebenso mehr Gewissheit wie mir selber und ihr habt nun aussagekräftigere
Ergebnisse.
Kommentar schreiben