diff --git a/chapters/thesis/chapter04.tex b/chapters/thesis/chapter04.tex index 88ff900..2c992e8 100644 --- a/chapters/thesis/chapter04.tex +++ b/chapters/thesis/chapter04.tex @@ -25,14 +25,16 @@ prüfen, die den Cache von OpenJPE auswerten} Um eine Messung der Performance in der Webseite durchführen zu können, gibt es in \ac{JSF} die Möglichkeit, über eine eigene Implementierung der Klasse \textbf{ViewDeclarationLanguageWrapper} sich in das generieren der Webseite einzuhängen. Hierbei können die Funktionen für das erstellen, des bauen und das rendern der Webseite überschrieben -werden. In den überschriebenen Funktionen können nun Messungen eingebaut werden, und diese Zeiten werden in eine -Log"=Datei eingetragen. +werden. In den überschriebenen Funktionen werden nun Laufzeiten gemessen und die ermittelten Zeiten mit einer Kennung +in die Log"=Datei eingetragen. Durch die Kennung, können die Zeiten im Nachgang über ein Script ermittelt und +ausgewertet werden. \mytodos{die VdlLogger und VdlLoggerFactory-Klasse als Appendix anhängen} Zusätzlich wird noch eine Implementierung der zugehörigen Factory"=Klasse \textbf{ViewDeclarationLanguageFactory} -benötigt. Diese Implementierung wird dann noch in der \textbf{faces-config.xml} eingetragen, dies wird in -\ref{lst:activate-fatory} gezeigt. +benötigt. Durch diese Factory"=Klasse wird der eigentlichen Wrapper mit der Performance-Messung in die Bearbeitungsschicht +eingehängt. Diese Implementierung wird dann noch in der \textbf{faces-config.xml} eingetragen, wie das in +\ref{lst:activate-fatory} gezeigt wird, damit die Factory durch das System aufgerufen wird. \begin{lstlisting}[language=xml,caption={Einbindung Factory},label=lst:activate-factory] diff --git a/chapters/thesis/chapter05.tex b/chapters/thesis/chapter05.tex index 207c36f..aa0a2e6 100644 --- a/chapters/thesis/chapter05.tex +++ b/chapters/thesis/chapter05.tex @@ -12,7 +12,7 @@ als Systemfestplatte ausgestattet. Zur ersten Untersuchung und der Bestimmung der Basis-Linie, wurde das Script ohne eine Änderung an dem Code und der Konfiguration mehrfach aufgerufen. Hierbei hat sich gezeigt, dass der erste Aufruf nach dem Deployment ca. 1500 ms -gedauert hat. Die weiteren Aufrufe dauert dann im Durchschnitt bei 600 ms. Beim achten Aufruf des Scripts hat der +gedauert hat. Die weiteren Aufrufe dauert dann im Durchschnitt noch 600 ms. Beim achten Aufruf des Scripts hat der Server nicht mehr reagiert und im Log ist ein OutOfMemoryError protokolliert worden. Nach einem Neustart des Servers, konnte das gleiche Verhalten wieder reproduziert werden. Daraufhin wurde das Test-Script @@ -21,10 +21,10 @@ Auswertung zeigte, dass der Server mit ca. 1500 MB RSS Nutzung an seine Grenzen Konfigurationsänderung im Payara-Server von \texttt{-Xmx512m} auf \texttt{-Xmx4096m} nach oben verschoben. Nun werden ca. 60 Aufrufe des Scripts benötigt, damit der Server nicht mehr reagiert. Hierbei wird aber kein OutOfMemoryError in der Log-Datei protokolliert und der Server verwendet nun ca. 4700 MB RSS. Bei allen Tests war noch mehr als die -Hälfte des verfügbaren Arbeitsspeichers unbenutzt. +Hälfte des verfügbaren Arbeitsspeichers des Computers ungenutzt. \mytodos{-Xmx definiert die Größe des Verwendbaren Heapspeichers} -Dies zeigt direkt, dass es ein problem in der Freigabe der Objekte gibt, da dass erhöhen des verwendbaren Arbeitsspeicher +Dies zeigt direkt, dass es ein Problem in der Freigabe der Objekte gibt, da dass erhöhen des verwendbaren Arbeitsspeicher das Problem nicht löst, sondern nur verschiebt. Als Grundlage für die Vergleiche wurden eine Messung durchgeführt, bei der alle Caches deaktiviert wurden und keine @@ -34,6 +34,7 @@ Ebenfalls sieht man eindeutig, dass die Anzahl der Anfragen nach dem ersten Aufr Der Speicherbedarf steigt auch relative gleichmässig, was nicht recht ins Bild passt, da hier keine Objekte im Cache gehalten werden sollten. +\mytodos{hier noch beschreiben, wie die Werte zu interpretieren sind, und hervorheben, dass dies nun für alle Tabellen so gilt!} \mytodos{hier noch text einfügen, der erklärt wie die Spalten zu werten sind, also Aufrufzeit ist kürzer gleich besser} \mytodos{Diese Tabelle vielleicht auch einfach komplett streichen, da der Datenbestand anders ist, und das wichtigste die Zeit der SQL-Abfragen nicht sichtbar ist} @@ -56,23 +57,26 @@ die Zeit der SQL-Abfragen nicht sichtbar ist} \label{tbl:measure-without-cache} \end{table} -\mytodos{hier noch beschreiben, wie die Werte zu interpretieren sind, und hervorheben, dass dies nun für alle Tabellen so gilt!} - Vor jedem weiteren Test-Lauf wurde die Domain beendet und komplett neugestartet, um mit einer frischen Instanz zu beginnen. Hierbei ist aufgefallen, dass fast immer 62 Abfragen zur Startup-Phase dazugehört haben, unabhängig von den -konfigurierten Cache Einstellungen. +konfigurierten Cache Einstellungen. Einige dieser Abfrage sind durch das erstellen der Materialisierten Sicht +\textbf{searchreference} erklärbar. Diese Sicht wird für die Suche benötigt, und da diese Seite nicht betrachtet hier +nicht betrachtet wird, wurde der Code für alle weiteren Tests deaktiviert. Da die Abfragezeiten auf der Datenbank zu gering waren, um eine Verbesserung feststellen zu können, wurde für den PostgreSQL und den Payara-Server ein Docker-Container erzeugt und diese limitiert. Die Konfiguration ist im Anhang \ref{ap:docker_config} beschrieben. Mit dem neuen Aufbau ergeben sich nun neue Messungen. Für den Speicherbedarf wird nun nicht mehr der benutzte -Speicher der Anwendung beobachtet, sondern die Speichernutzung des Docker-Containers für den Payara-Server. Für die -Ausführungszeiten der SQL-Abfragen wurden nur die 2 Hauptabfragen auf der Document-Tabelle, die Abfrage der 400 -Dokumente, sowie den letzten und ersten Eintrag der Tabelle. -\mytodos{es müssen die 6 Anfragen sein, document, first/last, documentaddresseeperson, documentcoauthorperson, documentfacsimile und count} +Speicher der Anwendung beobachtet, sondern die Speichernutzung des Docker-Containers für den Payara-Server. Auch hier +ist es besser, wenn es keine oder nur geringe Änderungen vor und nach dem Aufruf der Webseite gibt, ein steigender Wert +zeigt an, dass der verwendete Speicher nicht sauber freigegeben werden kann. + +Für die Ausführungszeiten der SQL-Abfragen wurden nur die sechs Abfragen für die Darstellung der Tabelle beachtet. +Hierzu zählt die Hauptabfrage der Dokumenten"=-Tabelle, die Ermittlung des letzten und ersten Eintrags in der Tabelle, +die Ermittlung der Adressen des Autors, die Ermittlung der CoAutoren, die Ermittlung der Faksimile, sowie die Ermittlung +der Anzahl aller vorhandenen Dokumente. -% document, first/last, documentaddresseeperson, documentcoauthorperson, documentfacsimile und count \begin{table}[h!] \centering \begin{tabular}{|r|r|r|r|r|r|r|r|r|} @@ -92,9 +96,20 @@ Dokumente, sowie den letzten und ersten Eintrag der Tabelle. \label{tbl:measure-without-cache-docker} \end{table} -\mytodos{searchreference-scheduler deaktivieren und hier angeben} \mytodos{die Reihenfolge der Sektion dem Schichtmodel anpassen} +\section{Umgestalten der Datenbanktabellen} +\label{sec:performance-investigation-application:new-table} + +Hierfür wurde die aktuelle Datenstruktur untersucht um zu prüfen, ob eine Umgestaltung der Tabelle einen Verbesserung +bringen würden. Die typische Optimierung ist die Normalisierung der Tabellenstruktur. Die Tabellenstruktur ist aktuell +schon Normalisiert, daher kann hier nichts weiter optimiert werden. + +Eine weitere optimierungsstrategie besteht in der Denormalisierung, um sich die Verknüpfungen der Tabellen zu sparen. +Dies ist in diesem Fall nicht anwendbar, da nicht nur 1:n Beziehungen vorhanden sind, sondern auch auch n:m Beziehungen. +Dadurch würden sich die Anzahl der Dokumentenliste erhöhen. Oder man muss die Duplikate auf der Serverseite +zusammenführen. + \section{Caching im OpenJPA} \label{sec:performance-investigation-application:caching-openjpa} @@ -102,13 +117,21 @@ Die Cache-Einstellung von OpenJPA werden über die zwei Einstellungen \texttt{op \texttt{openjpa.QueryCache} konfiguriert. Bei beiden Einstellungen kann zuerst einmal über ein einfaches Flag \textit{true} und \textit{false} entschieden werden ob der Cache aktiv ist. Zusätzlich kann über das Schlüsselwort \textit{CacheSize} die Anzahl der Elementen im Cache gesteuert werden. Wird diese Anzahl erreicht, dann werden zufällige -Objekte aus dem Cache entfernt und in eine SoftReferenceMap übertragen. +Objekte aus dem Cache entfernt und in eine SoftReferenceMap übertragen. Bei der Berechnung der Anzahl der Element werden +angeheftete Objekte nicht beachtet. + +Die Anzahl der Soft References kann ebenfalls über eine Einstellung gesteuert werden. Hierfür wird die Anzahl der +Elemente über \textit{SoftReferenceSize} gesetzt, dessen Wert im Standard auf \textit{unbegrenzt} steht. Mit dem Wert +\textit{0} werden die Soft Referencen komplett deaktiviert. Über die Attribute an den Entitätsklassen, können diese +Referenzen ebenfalls gesteuert werden, hierzu muss eine Überwachungszeit angegeben werden. Diese Zeit gibt in ms an, +wie lange ein Objekt gültig bleibt. Mit dem Wert \textit{-1} wird das Objekt nie ungültig, was ebenfalls der +Standardwert ist. Zuerst wird mit aktivierten Cache mit einer Cache-Größe von 1000 Elemente getestet. Wie in \ref{tbl:measure-ojpa-active} zu sehen, dauert auch hier der erste Aufruf minimal länger als ohne aktiviertem Cache. Alle Nachfolgenden Aufrufe -wiederrum sind um 100ms schneller in der Verarbeitung. Auch bei der Anzahl der Anfragen an die Datenbank kann mehr den -Rückgang der Anfragen sehr gut sehen. Aktuell kann die Verringerung des wachsenden Speicherbedarfs nur nicht erklärt -werden. +wiederrum sind um 100ms schneller in der Verarbeitung. Auch bei der Anzahl der Anfragen an die Datenbank kann der +Rückgang der Anfragen sehr gut gesehen werden. Aktuell kann die Verringerung des wachsenden Speicherbedarfs nur nicht +erklärt werden. \begin{table}[h!] \centering @@ -154,13 +177,43 @@ beschleunigt werden konnte. \label{tbl:measure-ojpa-active-bigger} \end{table} -\mytodos{pin und unpin noch mit einbringen? SoftReferenceMap nochmal genau durchleuchte, laut doku entfällt dort nichts -wenn kein Timeout auf der Klasse definiert ist} +\mytodos{Untersuchung mit deaktivieren SoftReference fehlt noch} + \mytodos{kurzes Fazit fehlt noch, anzahl der Queries für unterabfragen gehen auf 0 bzw. bleiben bei 400!} +\section{cached queries} +\label{sec:performance-investigation-application:cached-query} + +Über die Einstellung \textit{openjpa.jdbc.QuerySQLCache} wird der Cache für abfragen aktiviert. Hierbei können Abfragen +angeben werden, die aus dem Cache ausgeschlossen werden. Der QueryCache wiederrum beachtet aber nur Abfragen die keine +Parameter verwenden. Das sieht man auch entsprechend der Auswertung der Aufrufe \ref{tbl:measure-cached-queries}, +dass hier keine Veränderung der Aufrufzeiten stattgefunden hat. Gleich ob man mit \ac{JPQL} oder mit der Criteria API +abfragt. + +\begin{table}[h!] + \centering + \begin{tabular}{|r|r|r|r|r|r|r|r|} + \hline + & \multicolumn{3}{|c|}{Aufrufzeit (ms)} & & \multicolumn{3}{|c|}{RSS (MB)} \\ + \hline + \# & min & avg & max & Queries & davor & danach & diff \\ + \hline + 1 & 391 & 593 & 1533 & 12256 & 843.63 & 1009.79 & 116.16 \\ + 2 & 281 & 365 & 584 & 12080 & 996.28 & 1114.60 & 118.32 \\ + 3 & 295 & 353 & 464 & 12080 & 1103.30 & 1201.47 & 98.17 \\ + 4 & 280 & 292 & 324 & 12080 & 1191.56 & 1298.46 & 106.90 \\ + \hline + \end{tabular} + \caption{Messung mit aktiviertem Cached Queries} + \label{tbl:measure-cached-queries} +\end{table} + \section{Caching im \ac{JPA}} \label{sec:performance-investigation-application:caching-jpa} +\mytodos{muss noch umgebaut werden, falsche Konfiguration erwischt} + + Die Cache-Einstellungen von \ac{JPA} werden über mehrere Einstellungen konfiguriert. Anhand von \texttt{eclipselink.query-results-cache} wird definiert, dass die Ergebnisse von benannten Abfragen im Cache gespeichert werden. Für den Zugriff in den Cache, wird neben den Namen noch die übergebenen Parameter @@ -240,7 +293,7 @@ ORDER BY d.documentId ASC \end{lstlisting} In dem dazugehörigen Code am Server wird der JPQL-Code als NamedQuery hinterlegt und über den Name \textit{Document.findAll} -referenziert. In eingriff in die Abfrage ist hier leider nicht möglich, wie man im Code \ref{lst:jpql-document-list} +referenziert. Eine Veränderung der Abfrage ist hier leider nicht möglich, wie man im Code \ref{lst:jpql-document-list} sehen kann. \begin{lstlisting}[language=Java,caption={Java JPQL Dokumentenliste},label=lst:jpql-document-list] @@ -258,8 +311,8 @@ if(myResultList != null && !myResultList.isEmpty()) { } \end{lstlisting} -Da dieser Code direkt so aus dem Projekt kommt, wird hierfür keine gesonderte Zeitmessung durchgeführt, da dies durch -\ref{tbl:measure-without-cache} geschehen ist. +Da dieser Code direkt so aus dem Projekt kommt, wird hierfür keine gesonderte Zeitmessung durchgeführt, da diese der +Messung \ref{tbl:measure-without-cache} entspricht. \section{Abfragen Criteria API} \label{sec:performance-investigation-application:query-criteria-api} @@ -317,6 +370,9 @@ in den Java-Objekten fast identisch sind. Und in der Datenbank sind die Anfragen \label{tbl:measure-criteria-api} \end{table} +Daher bringt die Criteria API keinen performance Vorteil gegenüber der JPQL!=Implementierung. Somit können beide +Implementierung ohne bedenken gegeneinander ausgetauscht werden, und die verwendet werden, die für den Anwendungsfall +einfacher umzusetzen ist. \section{materialized views} \label{sec:performance-investigation-application:materialized-views} @@ -327,7 +383,8 @@ die gespeicherten Daten zugegriffen. Dies ist gerade bei vielen Joins von Vortei Sichten auch Indexe erstellt werden, um noch effektiver die Abfragen bearbeiten zu können. Der größte Nachteil dieser Sichten ist, dass sie zyklisch oder bei Datenänderungen aktualisiert werden müssen, sonst -läuft der Datenbestand der Sicht und der zugrundeliegenden Abfrage auseinander. +läuft der Datenbestand der Sicht und der zugrundeliegenden Abfrage auseinander. Da die Hauptarbeiten auf der Webseite +die Abfrage der Daten ist, und nicht das editieren, kann dieser Nachteil bei entsprechender Optimierung igoriert ewrden. In diesem Test, wurde zusätzlich zur normalen Abfragen noch die nachfolgenden einzelabfragen als Sub-Selects hinzugefügt, wie in \ref{lst:sql-materialized-view} zu sehen. Somit können die nachfolgenden einzelnen Abfragen @@ -437,7 +494,9 @@ LEFT JOIN sitecity sc ON sc.id = d.city_id; Wie in Tabelle \ref{tbl:measure-materialized-view} zu sehen, bringt die Verwendung der Materialized View ein Verbesserung in verschiedenen Punkten. Zum einen ist eine Verbesserung der Aufrufzeiten zu erkennen, zusätzlich fällt der -Speicheranstieg weniger stark aus. +Speicheranstieg weniger stark aus. Die Verbesserung der Aufrufzeiten lässt sich zusätzlich erklären, dass hier nun +nur noch vier statt der 6 Abfragen an die Datenbank gestellt werden, da einzelabfragen für die Adressen der Personen +und der CoAutoren komplett entfallen. Nach dem der Quellcode nochmal untersucht wurde, konnte man festellen, dass bei jeder Anfrage die gleiche Bedingung benötigt wurde. Da die Sicht nun explizit für dies Anfrage geschaffen wurde, wurde die Bedingungen nun direkt in Sicht @@ -471,46 +530,11 @@ Nach dem Anpassungen haben sich dann die Werte aus \ref{tbl:measure-materialized \label{tbl:measure-materialized-view-ext} \end{table} -\mytodos{hier noch darauf eingehen, dass die Hauptarbeit nicht beim editieren sondern bei der Anzeige ist} +%\mytodos{hier noch darauf eingehen, dass die Hauptarbeit nicht beim editieren sondern bei der Anzeige ist} \mytodos{Das Render des Json in der View Betrachten, scheint der aktuelle Kostenpunkt zu sein} \mytodos{Hier könnte man auch den Query-Cache nochmal verwenden, da die anfragen nun fix wären} \mytodos{Grundlagen zur Materialized-View noch hinterlegen} -\section{cached queries} -\label{sec:performance-investigation-application:cached-query} - -Über die Einstellung \textit{openjpa.jdbc.QuerySQLCache} wird der Cache für abfragen aktiviert. Hierbei können Abfragen -angeben werden, die aus dem Cache ausgeschlossen werden. Der QueryCache wiederrum beachtet aber nur Abfragen die keine -Parameter verwenden. Das sieht man auch entsprechend der Auswertung der Aufrufe \ref{tbl:measure-cached-queries}, -dass hier keine Veränderung der Aufrufzeiten stattgefunden hat. Gleich ob man mit \ac{JPQL} oder mit der Criteria API -abfragt. - -\begin{table}[h!] - \centering - \begin{tabular}{|r|r|r|r|r|r|r|r|} - \hline - & \multicolumn{3}{|c|}{Aufrufzeit (ms)} & & \multicolumn{3}{|c|}{RSS (MB)} \\ - \hline - \# & min & avg & max & Queries & davor & danach & diff \\ - \hline - 1 & 391 & 593 & 1533 & 12256 & 843.63 & 1009.79 & 116.16 \\ - 2 & 281 & 365 & 584 & 12080 & 996.28 & 1114.60 & 118.32 \\ - 3 & 295 & 353 & 464 & 12080 & 1103.30 & 1201.47 & 98.17 \\ - 4 & 280 & 292 & 324 & 12080 & 1191.56 & 1298.46 & 106.90 \\ - \hline - \end{tabular} - \caption{Messung mit aktiviertem Cached Queries} - \label{tbl:measure-cached-queries} -\end{table} - -\section{Umgestalten der Datenbanktabellen} -\label{sec:performance-investigation-application:new-table} - -\mytodos{Erwähnen des Ansatz, von denormalisierung inkl. Grund warum es weg gelassen wurde} - -\section{Verkleinerung der Abfragen} -\label{sec:performance-investigation-application:smaller-query} - \section{Java Server Faces} \label{sec:performance-investigation-application:java-server-faces} @@ -538,12 +562,16 @@ Render der Sicht auftritt. Wenn man nun noch die Abfrage auf die Materialized-Vi \label{sec:performance-investigation-application:static-website} Wenn man die Dokumentenliste als statische Webseiten ablegt, werden die Zugriffszeiten sehr kurz sein. Darüber hinaus -funktionieren in statische Webseiten aber keine Suche oder eine Sortierung. Sonst müsste man für jede mögliche -Sortierung und Suchanfrage einen Satz der Dokumentenliste als statische Webseite bereitstellen. Für die Sortierungen -wäre das noch möglich, aber für die Suchanfragen ist dies nicht mehr möglich. Daher ist die Umstellung auf statische -Webseiten nicht sinnvoll. +funktionieren in statische Webseiten aber keine Suche oder eine Sortierung. Die Sortierung könnte durch das erstellen +von statischen Seite aller Möglichkeiten der Sortierung emuliert werden, diese würde den notwendigen Speicherbedarf der +Webseite vervielfachen. Für die Suchanfragen ist dies nicht mehr möglich, da nicht alle Suchanfragen vorher definiert +werden können. -\mytodos{Hier noch explizirter definieren, dass die sortierten Daten als statische Seiten abgelegt werden} +Die Umstellung der Suche auf Client!=Basis wäre noch eine Möglichkeit, dafür benötigen die Clients entsprechend +Leistung und es muss eine Referenzdatei erstellt werden, die alle Informationen über die Dokumente beinhaltet, nach der +gesucht werden kann. + +Daher ist eine Umstellung auf statische Webseiten nicht sinnvoll. \section{Client basierte Webseiten} \label{sec:performance-investigation-application:client-side-rendering} diff --git a/thesis.pdf b/thesis.pdf index 0863f10..ae7d59d 100644 Binary files a/thesis.pdf and b/thesis.pdf differ