Vaadin unter Last – Teil 2: Ergebnisse der Lasttests (Antwortzeit)

Wir haben im ersten Teil gezeigt, wie ein Lasttest für eine Vaadin-Anwendung mit dem OpenSource-Programm JMeter aufgebaut werden kann. Als Beispiel diente der Officewerker, eine Anwendung zum Office-Management in kleinen Unternehmen oder Teams. Dieser Artikel – wieder auf Basis des Officewerkers – beleuchtet nun eine konkrete Testreihe auf der Cloud-Plattform EC² (Elastic Computing Cloud) von Amazon. Der Fokus liegt dabei auf dem Antwortzeitverhalten bei immer mehr Anfragen – und den entstehenden Bottlenecks. Dabei beleuchten wir vor allem die Rolle von Vaadin.

Zur Durchführung des Tests verwenden wir zwei Server auf der EC²:

  • Einen Server als Application Server für den Officewerker – dieser Server wird unter Last gesetzt.
  • Einen Server zur Ausführung des Testprogramms unter JMeter – dieser Server erzeugt die Last.

Die Server sind wie folgt ausgestattet:

  RAM Cores
Server unter Last 15 GB 8 Cores
Test-Treiber-Server 7,5 GB 4 Cores

Da sich beide Server im EC²-Netz befinden, ist von einem sehr performanten Netzwerk mit vernachlässigbarem Einfluss auszugehen. Das JMeter-Testprogramm simuliert die vom Browser gestellten Netzwerk-Anfragen. Ziel des Tests ist also die Server-Seite von Vaadin.

Was wir also nicht testen, ist die Performance des Netzwerks (auf die Vaadin keinen Einfluss hat) und die Client-Seite von Vaadin. Da diese allerdings nur genau eine Sitzung bedient, ist sie nach unserem Dafürhalten zunächst vernachlässigbar. Die Möglichkeit eines „sofortigen“ Tests einer Vaadin Anwendung im eigenen Browser bieten die Beispiel-Anwendungen von Vaadin unter https://vaadin.com/demo

Der Test führt nun eine Reihe von Aktionen durch:

  • Aufruf der Startseite
  • Laden der Ressourcen (JavaScripts, Bilder, etc.) für eine realistische Simulation
  • Einloggen (Schritt 1)
  • Wechsel auf die Startseite (Schritt 2)
  • Wechsel auf die Liste der Eingangsrechnungen (Schritt 3)
  • Suche nach einer Rechnungsnummer (Schritt 4)

Die Schritte 2 und 3 vernachlässigen wir hier, da weder in der UI- noch in der Business-Schicht etwas Spannendes passiert. Diese beiden Schritte waren auch bei der Performance-Messung unauffällig. Daher werden wir im Folgenden die Schritte 1 und 4 mitsamt deren Spezifika näher beleuchten.

Test von Schritt 1: Einloggen

LoginOfficewerker

Die folgende Tabelle zeigt die Ergebnisse von drei Läufen mit JMeter. Die Spalten haben dabei folgende Bedeutungen:

  • Threads – Anzahl der Threads, die gleichzeitig auf die Anwendung zugreifen
  • Durchläufe – Anzahl der Durchläufe, die jede Thread durchführt
  • # – Anzahl der Ausführungen von Schritt 1 (Logins)
  • Avg – Durchschnittliche Antwortzeit
  • Dev –Standardabweichung von der durchschnittlichen Antwortzeit
Threads Durchläufe # Avg [ms] Dev [ms]
50 20 1000 4800 1191,55
100 20 2000 9335 2332,37
200 20 4000 19423 4504,16

Dabei wird deutlich, dass ein praktisch lineares Wachstum vorliegt. Sprich: je mehr simulierte Nutzer gleichzeitig auf die Anwendung zugreifen, desto länger müssen diese Nutzer beim Login warten.

Es ist darüber hinaus evident, dass das Ergebnis schwer als zufriedenstellend betrachtet werden kann. Die Vermutung, dass lineares Wachstum (oft) durch Thread-Synchronisation hervorgerufen wird, bestätigt sich beim Blick in den Quelltext: Bei der Anmeldung wird synchronisiert auf ein Objekt zugegriffen, das Session-übergreifend verwendet wird.

Wenn die Stelle im Quelltext nicht so offensichtlich wie in unserem Beispiel ist, können derartige Probleme auch über Tools (z.B. JVisualVM) aufgespürt werden. Auch lässt sich der Anteil am Zeitverbrauch von Vaadin, der Geschäftslogik und des Anwendungsservers genauer aufschlüsseln. Im übernächsten Abschnitt beschreiben wir dies genauer.

Test von Schritt 4: Suche nach einer Rechnungsnummer

EingangsrechnungSuchen

Die Ergebnisse des Tests sind wieder in einer Tabelle dargestellt. Folgende Spalten sind hinzugekommen bzw. haben eine andere Bedeutung:

  • Rechnungen – Anzahl der Rechnungen, die pro Durchlauf gesucht werden
  • Sockets/DB – Anzahl der Datenbankverdingungen aus dem Application Server zur Datenbank
  • # – Anzahl Ausführungen von Schritt 4
Threads Durchläufe Rechnungen Sockets (DB) # Avg [ms] Dev [ms]
50 20 10 14 10000 71 53,41
100 20 10 12 20000 70 50,20
200 20 10 14 40000 72 76,03

Dieser Test hat nun eindeutig kein lineares Wachstum. Vielmehr bleibt das Antwortzeitverhalten bei der Verdopplung von 50 auf 100 unverändert. Gleiches gilt für die der Erhöhung von 100 auf 200 simulierte parallele Benutzer. Lediglich die Streuung um den Mittelwert (Standardabweichung) steigt etwas an.

Es ist an dieser Stelle entscheidend, dass pro Request eine andere Rechnungsnummer abgefragt wird – sprich: es erfolgt bei jeder Anfrage ein Zugriff von Vaadin über die Business-Schicht bis in die Datenbank. Der durchschnittliche Zeitbedarf hierfür beschränkt sich auf nicht wahrnehmbare ~70 Millisekunden für jede der gezogenen 40.000 Rechnungen. 3 von 4 Anfragen sind in weniger als ~150 Millisekunden abgearbeitet.

Dies lässt den Schluss zu, dass das Antwortverhalten vor allem vom Backend hinter Vaadin abhängig ist. Ist dieses (wie im Schritt 1 erkannt) nicht effizient, ist es auch die Anwendung in Summe nicht. Ist es allerdings (wie in Schritt 4 gemessen und aufgezeigt) effizient, dann ist auch die Anwendung in Summe effizient.

Um diese These weiter zu härten haben wir die Last auf Schritt 4 weiter erhöht, und zwar um das 50-fache auf 500 abgerufene Rechnungen.

Test von Schritt 4: Suche nach einer Rechnungsnummer II – modifiziert

Threads Durchl. Rechnungen Sockets (DB) # Avg [ms] Dev [ms]
200 20 10 14 40000 72 76,03
200 20 500 32 197170 2380 782,58

Anmerkung: Der Test in der zweiten Zeile wurde aus Zeitgründen nach ca. 10% Fortschritt abgebrochen.

Bei diesem Test mit erheblich mehr Datenbankabfragen wird eine deutlich höhere Last auf dem Backend erwartet. Die obige Tabelle zeigt für den Sprung von 10 auf 500 Rechnungs-Abfragen pro Benutzer (also auf das 50-fache) eine ver-47-Fachung der Antwortzeit an. Um diesem Phänomen auf den Grund zu gehen, analysieren wir nun eine Stufe tiefer: Wir betrachten die Zeit, die entlang des Aufrufs von Vaadin über die Business-Schicht (in Form von EJBs) bis in die Datenbank jeweils in den Methoden verbracht wird („Self Time“ – sie ist eine „Wall Clock Time“, sie betrachtet also nicht den CPU-Verbrauch, sondern den für uns hier interessanten Zeitverbrauch für die Methode).

Für die Analyse haben wir auf JVisualVM (http://docs.oracle.com/javase/6/docs/technotes/tools/share/jvisualvm.html) zurückgegriffen, die einen detaillierten Einblick in JVMs (auch in entfernte) ermöglicht.

Das Ergebnis ist in der folgenden Grafik dargestellt:

Zeitverbrauch-Methoden

Der Vollständigkeit halber haben wir auch untersucht, welche Zeit auf die Verbrauchs-intensivste Vaadin-Methode entfällt.

Zeitverbrauch-Vaadin

Dieses Ergebnis zeigt sehr deutlich, dass die Persistenzschicht den Löwenanteil der Aufrufzeit verbraucht. Alleine die erste Methode zeichnet sich für 57% der Antwortzeit verantwortlich.

Betrachtet man die ersten drei Methoden, so fällt auf, dass

  • sich alle Methoden im Bereich der EJB-Schicht oder dahinter befinden – sprich: im Backend angesiedelt sind
  • diese für 98% der gesamten Self-Time verantwortlich sind

Die Verdopplung der an die Datenbank geöffneten Sockets (vgl. obige Tabelle) unterstreicht diese Erkenntnis abermals. Dem gegenüber liegt die in Bezug auf Zeitverbrauch „teuerste“ Methode aus dem Vaadin-Framework im nicht mehr messbaren Bereich (0%).

Fazit

Damit ist auch hier festzuhalten, dass die Performance einer Vaadin-Anwendung (zumindest was die Antwortzeit betrifft) durch die Performance des Backends konstitutiv bestimmt ist. Das Bottleneck war in Schritt 1 die synchronisierte Business-Logik und in Schritt 4 bei entsprechender Last die Datenbank. In beiden Fällen gilt es, das Backend des Officewerker nachzubessern. Die Bereitstellung der UI über Vaadin hat einen vernachlässigbar geringen Anteil an der Antwortzeit. Die Anwendung ist so performant (oder so nicht-performant) wie ihr Backend.

Im dritten und letzten Teil beleuchten wir den Speicherverbrauch von Vaadin während  der Lasttests.

Wenn Sie Fragen haben, schreiben Sie einfach einen Kommentar oder schreiben Sie uns eine E-Mail:

oliver.damm [at] akquinet.de
sebastian.rothbucher [at] akquinet.de

Ein Gedanke zu “Vaadin unter Last – Teil 2: Ergebnisse der Lasttests (Antwortzeit)

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s