Und wie wirkt sich das auf die Performance aus? (Teil 1)

Solche oder ähnliche Fragen zum Thema Performance hören wir oft, wenn es um die Verarbeitung größerer Datenmengen geht.
Unsere Antwort lautet meistens mit sehr viel Ernst und einem Augenzwinkern ;) : “Immer schlecht.”

In diesem Artikel lernen Sie, wie sie durch Caching die Ausführungsgeschwindigkeit von Flows drastisch steigern können.

Viel = langsamer

Mehr ist immer langsamer, klar oder?
Synesty erlaubt sehr viel Spielraum beim Erstellen von Flows. Die Art und Weise, wie man Steps miteinander kombinieren kann ermöglich große Flexibilität.
Leider kommt diese Flexibilität oft mit dem Preis der Komplexität und Performance. Und mit viel meinen wir nicht nur eine Datenquelle mit sehr vielen Zeilen, sondern viele Zeilen und viele Steps, die diese verarbeiten – sozusagen das Produkt aus Zeilen x Anzahl Steps.

Durch Caching (einer Art Puffer oder Zwischenspeicher) kann man vermeiden, dass bestimmte kostspielige Aufgaben unnötig oft gemacht werden, sondern im Optimalfall nur einmal.

In diesem Blogbeitrag wollen wir Ihnen einige Hintergründe erklären, wie man Performanceprobleme erkennt und was man dagegen machen kann.

Mapper und Filter – Da bringt der Cache sehr viel.

Die Steps mit dem höchsten Tuning-Potential sind Mapper und Filter. Durch diese beiden Steps fließen massenhaft Spreadsheet-Zeilen und Spalte durch, so dass man hier sehr viel richtig oder auch falsch machen kann. In diesem Artikel betrachten wir den Mapper genauer.

Mit der Querverweis-Funktion im Mapper kann man ein Spreadsheet mit Daten aus einem oder mehreren Datastores anreichern. Dabei wird anhand eines identifiers (z.B. Produktnummer) in einen Datastore geschaut, ob es dort einen passenden Datensatz gibt, um dessen Daten zu verwenden. Dieses Nachschauen im Datastore wird pro Spalte und pro Zeile gemacht, in der man die Querweis-Funktion anwendet.

Beispiel:

  • gegeben sei ein Spreadsheet mit 5 Spalten und 10 Zeilen.
  • in 3 Spalten wird ein Querverweis verwendet
  • D.h. es wird 3 x 10 = 30 mal in den Datastore geschaut.

Hier nochmal visuell zur Verdeutlichung als Tabelle:

EANMengeBeschreibung (Querverweis mit EAN=Produktdatastore.identifier2)Preis (Querverweis mit EAN=Produktdatastore.identifier2)BildURL (Querverweis mit EAN=Produktdatastore.identifier2)
10Description …. wird per Querverweis aus Datastore anhand der EAN ermittelt49,99 …wird per Querverweis aus Datastore anhand der EAN ermitteltImage1.jpg … wird per Querverweis aus Datastore anhand der EAN ermittelt
21
36
449
523
6468
735
836
94
101


Das bezeichnet man auch als teuer, da dieses Nachschauen, im Vergleich zu anderen Dingen (z.B. einer einfachen Berechnung) recht langsam ist.

Soll ich auf Querverweise verzichten?

Nein. Querverweise zu benutzen ist völlig in Ordnung und ein sehr nützliches und mächtiges Werkzeug.
Wann aber leidet die Performance?

Richtig teuer wird es, wenn man das Ausgabe-Spreadsheet dieses Querverweis-Mappers, in mehr als einem weiteren Steps verarbeitet.
Denn die die Querverweise werden jedes mal erneut ausgeführt. D.h. wenn dieses Spreadsheet z.B. von 3 weiteren Steps verwendet wird (z.B. 3 CSVWriter um 3 verschiedene CSV-Dateien zu erzeugen) dann werden in unserem Beispiel oben statt nur 30 Datastore-Zugriffen 90 Zugriffe ausgeführt. Dadurch dauert die Flowausführung fast 3 mal so lange.

Warum ist das so?
Diese wiederholte Neuausführung liegt daran, dass der Mapper “lazy” arbeitet. D.h. die Verarbeitung im Mapper findet erst statt, wenn auch ein anderer Step die Zeilen dieses Spreadsheets liest – sprich “konsumiert”. Diese sog. lazy-Evaluation hat große Vorteile, da eine Verarbeitung im Mapper nur stattfindet, wenn es auch einen konsumierenden Step gibt. Das spart Rechenpower, wenn z.B. ein konsumierender Step nach der Hälfte der Zeilen aufhört zu lesen, dann muss der Mapper auch nur die Hälfte der Zeilen verarbeiten.
Das ist der Grund, warum die Step-Vorschau eines Mappers blitzschnell die erste Vorschauzeile anzeigt, obwohl die Datenquelle z.B. eine CSV-Datei eine halbe Million Zeilen beinhaltet. Es wird nur die erste in der Vorschau sichtbare Zeile verarbeitet und danach erstmal gestoppt. Die komplette Datei, wird dann erst zur eigentlichen Flow-Ausführung verarbeitet. Diese “lazy”-Verarbeitung ist oft anders als Nutzer denken und führt evtl. zur Verwirrung. Oft wird gedacht, dass nach der Ausführung des Mappers immer das komplette Ergebnis vorliegt. Das ist nicht so, aus genannten Gründen.

Und nun?

Nun wissen wir, dass jeder konsumierende Step, einen Mapper immer wieder erneut durchläuft. Was aber kann man dagegen tun? Gibt es einen Weg, das zu verhindern?
Ja. Durch Caching im Mapper.

Der Mapper hat eine Option Cache aktivieren. Diese sorgt dafür, dass das Ergebnis des SpreadsheetMappers im Hintergrund bei der ersten Verarbeitung eines Folgesteps zwischengespeichert wird. D.h. jede weitere Verarbeitung dieses Spreadsheets greift auf die gecachten Daten aus dem ersten Durchlauf zu. Dadurch werden die ganzen Datastore-Zugriffe nur ein einziges mal gemacht – also nur 30 statt 90 Zugriffe, bezogen auf das Beispiel weiter oben.


Weiterer Vorteil: Durch die Speicherung im Datei-Cache wird auch wertvoller Server-Arbeitsspeicher wieder freigegeben, der dann wieder anderen Prozessen zur Verfügung steht.

Wie kann ich herausfinden, ob ein Mapper-Ergebnis mehr als einmal verwendet wird?

Über die Ansicht Datenflussgraph kann man sehen, wie die Steps miteinander verbunden sind.
Die rot markierten Steps sind Mapper, deren Output jeweils zwei mal verwendet wird. Das erkennt man daran, dass jeweils zwei Pfeile aus diesem Mapper abgehen.
Damit sind das gute Kandidaten, um den Cache zu aktivieren.

Wann ist der Cache auch noch sinnvoll?

Querverweise sind nicht die einzige Funktion, die durch den Cache beschleunigt werden können. Weitere Funktionen sind:

  • Gruppieren im Mapper
  • Filter Step

Gruppieren

Gruppieren ist eine sehr hilfreiche Funktion im Mapper, um Daten zu aggregieren bzw. zusammenzufassen. Aus der SQL-Welt kennt man das als GROUP BY.
Diese Funktion ist im Hintergrund allerdings relativ teuer, da sie sich durch alle Daten eines Spreadsheets graben muss, um diese zusammenzufassen. Das möchte man nur ein einziges mal machen.

D.h. auch hier gilt: Wenn man mit einem Mapper große Spreadsheets verarbeitet und die Gruppieren-Funktion verwendet, dann bringt der Cache einen spürbaren Leistungsschub. Beim Gruppieren empfiehlt sich die Aktivierung des Caching nahezu immer, da auf diese Weise, das Gruppierte Ergebnis nicht im Speicher gehalten werden muss, was mehr Reserven für den Rest des Flows frei macht und damit die Ausführung beschleunigt.

Fazit

In diesem Artikel haben wir Wirkungsweise des Cache-Modus im Mapper Step vorgestellt. Im Teil 2 dieser Reihe, werden wir uns das Thema Performance im Zusammenhang mit dem Filter anschauen.


Photo by Mika Baumeister on Unsplash