diff --git a/chapters/thesis/appendix02.tex b/chapters/thesis/appendix02.tex index 355be1d..82243e0 100644 --- a/chapters/thesis/appendix02.tex +++ b/chapters/thesis/appendix02.tex @@ -1,3 +1,5 @@ +% !TeX root = ../../thesis.tex + %******************************************************************** % Appendix %******************************************************* diff --git a/chapters/thesis/appendix02_timing.sh b/chapters/thesis/appendix02_timing.sh index 28537ee..8b8f3bf 100644 --- a/chapters/thesis/appendix02_timing.sh +++ b/chapters/thesis/appendix02_timing.sh @@ -84,8 +84,9 @@ hostname="http://localhost:8080/WedekindJSF-1.0.0" # the Array of the Urls url_arr=( "$hostname/index.xhtml" - "$hostname/view/document/list.xhtml" - #"$hostname/view/correspondent/list.xhtml" + #"$hostname/view/document/list.xhtml" + "$hostname/view/document/list_mv.xhtml" + #"$hostname/view/correspondent/list.xhtml" #"$hostname/view/person/list.xhtml" ) diff --git a/chapters/thesis/chapter01.tex b/chapters/thesis/chapter01.tex index 063d7dc..030c620 100644 --- a/chapters/thesis/chapter01.tex +++ b/chapters/thesis/chapter01.tex @@ -1,3 +1,4 @@ +% !TeX root = ../../thesis.tex \chapter{Einleitung} \label{ch:intro} diff --git a/chapters/thesis/chapter02.tex b/chapters/thesis/chapter02.tex index 8ae8b91..b90174a 100644 --- a/chapters/thesis/chapter02.tex +++ b/chapters/thesis/chapter02.tex @@ -1,3 +1,4 @@ +% !TeX root = ../../thesis.tex \chapter{Grundlagen} \label{ch:basics} diff --git a/chapters/thesis/chapter03.tex b/chapters/thesis/chapter03.tex index ce449c7..0792d3e 100644 --- a/chapters/thesis/chapter03.tex +++ b/chapters/thesis/chapter03.tex @@ -1,3 +1,4 @@ +% !TeX root = ../../thesis.tex \chapter{Konzept} \label{ch:concept} diff --git a/chapters/thesis/chapter04.tex b/chapters/thesis/chapter04.tex index 90114ef..e5d4365 100644 --- a/chapters/thesis/chapter04.tex +++ b/chapters/thesis/chapter04.tex @@ -1,3 +1,4 @@ +% !TeX root = ../../thesis.tex \chapter{Performance-Untersuchung} \label{ch:performance-checking} @@ -51,7 +52,7 @@ Dies zeigt direkt, dass es ein problem in der Freigabe der Objekte gibt, da dass 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 -Änderung am Code vorgenommen wurde. Das Ergebnis dieser Messung ist in \ref{tab:MeasureWithoutCache} zu finden. Diese +Änderung am Code vorgenommen wurde. Das Ergebnis dieser Messung ist in \ref{tbl:measure-without-cache} zu finden. Diese zeigen auch direkt ein erwartetes Ergebnis, dass der erste Aufruf bedeutend länger dauert als die Nachfolgenden. Ebenfalls sieht man eindeutig, dass die Anzahl der Anfragen nach dem ersten Aufruf immer die gleiche Anzahl besitzen. Der Speicherbedarf steigt auch relative gleichmässig, was nicht recht ins Bild passt, da hier keine Objekte im Cache @@ -72,7 +73,7 @@ gehalten werden sollten. \hline \end{tabular} \caption{Messung ohne Caches} - \label{tab:MeasureWithoutCache} + \label{tbl:measure-without-cache} \end{table} Vor jedem weiteren Test-Lauf wurde die Domain beendet und komplett neugestartet, um mit einer frischen Instanz zu @@ -88,8 +89,8 @@ Die Cache-Einstellung von OpenJPA werden über die zwei Einstellungen \texttt{op \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. -Zuerst wird mit aktivierten Cache mit einer Cache-Größe von 1000 Elemente getestet. Wie in \ref{tbl:MeasureOJPAactive} -zu sehen, dauert auch hier der erste Aufruf minimal länger als ohne akivierten Cache. Alle Nachfolgenden Aufrufe +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 akiviertem 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. @@ -109,11 +110,11 @@ werden. \hline \end{tabular} \caption{Messung mit OpenJPA-Cache und Größe auf 1000} - \label{tbl:MeasureOJPAactive} + \label{tbl:measure-ojpa-active} \end{table} Bei einer erhöhten Cache-Größe, zeigt sich auf den ersten Blick ein noch besseres Bild ab, wie in -\ref{tbl:MeasureOJPAactivebigger} ersichtlich ist. Der erste Aufruf entspricht der Laufzeit mit geringerer Cache-Größe, +\ref{tbl:measure-ojpa-active-bigger} ersichtlich ist. Der erste Aufruf entspricht der Laufzeit mit geringerer Cache-Größe, aber schon die Anfragen an die Datenbank gehen drastisch zurück. Bei den weiteren Aufrufen werden im Schnitt nun nur noch 6 Anfragen pro Seitenaufruf an die Datenbank gestellt, wodurch die Laufzeit im Schnitt nochmal um 100 ms beschleunigt werden konnte. @@ -133,7 +134,7 @@ beschleunigt werden konnte. \hline \end{tabular} \caption{Messung mit OpenJPA-Cache und Größe auf 10000} - \label{tbl:MeasureOJPAactivebigger} + \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 @@ -184,6 +185,7 @@ Anzahl der Abfragen an die Datenbank drastisch reduziert werden. Selbst die Lauf \label{sec:performance-checking:investigation-application:caching-ejb} Die Cache-Einstellungen des \ac{EJB} sind in der Admin-Oberfläche des Payara-Servers zu erreichen. Hier +\mytodos{Cache config noch definieren} \begin{table}[h!] \centering @@ -199,19 +201,111 @@ Die Cache-Einstellungen des \ac{EJB} sind in der Admin-Oberfläche des Payara-Se 4 & 281 & 318 & 398 & 12080 & 1191.25 & 1305.29 & 114.04 \\ \hline \end{tabular} - \caption{Messung mit OpenJPA-Cache und Größe auf 10000} - \label{tbl:MeasureEJBAactive} + \caption{Messung mit \ac{EJB}-Cache} + \label{tbl:measure-ejb-cache-active} \end{table} -\subsection{Abfragen JPQL} +\subsection{Abfragen \ac{JPQL}} \label{sec:performance-checking:investigation-application:query-jpql} +Für die \ac{JPQL} wird ein \ac{SQL} ähnlicher Syntax verwendet um die Abfragen an die Datenbank durchzuführen. Für die +Dokumentenliste wird der Code aus \ref{lst:jpql-document-list-jpql} verwendet. Die Namen mit vorangestellten Doppelpunkt +sind Übergabevariablen. + +\begin{lstlisting}[language=Java,caption={JPQL Dokumentenliste},label=lst:jpql-document-list-jpql] +SELECT DISTINCT d FROM Document d +LEFT JOIN FETCH d.authorPerson +LEFT JOIN FETCH d.coauthorPersonSet +LEFT JOIN FETCH d.addresseePersonSet +WHERE d.validUntil > :now +AND d.isPublishedInDb = :published +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} +sehen kann. + +\begin{lstlisting}[language=Java,caption={Java JPQL Dokumentenliste},label=lst:jpql-document-list] +List myResultList = createNamedTypedQuery("Document.findAll") + .setParameter("now", _IncludeDeleted ? new Date(0) : Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())) + .setParameter("published", true) + .setFirstResult(_Start) + .setMaxResults(_Size) + .setHint("javax.persistence.query.fetchSize", _Size) + .getResultList(); + +// Uebergabe der Ergebnisliste +if(myResultList != null && !myResultList.isEmpty()) { + myResult.addAll(myResultList); +} +\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. + \subsection{Abfragen Criteria API} \label{sec:performance-checking:investigation-application:query-criteria-api} +Für die Criteria API wird die Abfrage nicht in einem SQL-Dialekt beschreiben. Hierbei werden über Attribute die +Verlinkung zur Datenbank durchgeführt. An der Klasse selbst wird der Tabellenname definiert und an den Attributen die +Spaltennamen. Um die Anfrage durchführen muss nun nur noch Datenklasse angegeben werden und mit den Parametern +versorgt werden, wie es in \ref{lst:criteria-api} gezeigt wird. + +\begin{lstlisting}[language=Java,caption={Criteria API Dokumentenliste},label=lst:criteria-api] +CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); +CriteriaQuery cq = cb.createQuery(Document.class); +Root from = cq.from(Document.class); +ParameterExpression includedPara = cb.parameter(Boolean.class, "published"); +ParameterExpression validPart = cb.parameter(Date.class, "now"); + +CriteriaQuery select = cq.select(from) + .where(cb.and( + cb.equal(from.get("isPublishedInDb"), includedPara), + cb.greaterThan(from.get("validUntil"), validPart) + )); +TypedQuery typedQuery = getEntityManager().createQuery(select) + .setParameter("now", _IncludeDeleted ? new Date(0) : Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())) + .setParameter("published", true) + .setFirstResult(_Start) + .setMaxResults(_Size) + .setHint("javax.persistence.query.fetchSize", _Size); +List myResultList = typedQuery.getResultList(); + +// Uebergabe der Ergebnisliste +if (myResultList != null && !myResultList.isEmpty()) { + myResult.addAll(myResultList); +} +\end{lstlisting} + +Wie in der Messung \ref{tbl:measure-criteria-api} zu sehen, unterscheiden sich die Abfragezeiten nur marginal von +denen mit \ac{JPQL}. Wenn man sich den Code im Debugger anschaut, sieht man auch, dass die zusammengesetzten Abfragen +in den Java-Objekten fast identisch sind. Und in der Datenbank sind die Anfragen identisch zu denen über JPQL. + +\begin{table}[h!] + \centering + \begin{tabular}{|r|r|r|r|r|r|r|r|} + \hline + & \multicolumn{3}{|c|}{Aufrufzeit} & & \multicolumn{3}{|c|}{RSS} \\ + \hline + \# & min & avg & max & Queries & davor & danach & diff \\ + \hline + 1 & 396 & 572 & 1535 & 12173 & 796.59 & 970.10 & 173.51 \\ + 2 & 333 & 366 & 397 & 12080 & 982.28 & 1064.12 & 81.84 \\ + 3 & 286 & 339 & 554 & 12080 & 1048.12 & 1162.92 & 114.80 \\ + 4 & 293 & 317 & 388 & 12080 & 1150.43 & 1263.77 & 113.34 \\ + \hline + \end{tabular} + \caption{Messung mit Criteria-API ohne Cache} + \label{tbl:measure-criteria-api} +\end{table} + + \subsection{materialized views} \label{sec:performance-checking:investigation-application:materialized-views} +\mytodos{Sourcecode erfragen bei Herrn Holstein!} + \subsection{cached queries} \label{sec:performance-checking:investigation-application:cached-query} diff --git a/chapters/thesis/chapter05.tex b/chapters/thesis/chapter05.tex index 27f806c..6fc5577 100644 --- a/chapters/thesis/chapter05.tex +++ b/chapters/thesis/chapter05.tex @@ -1,3 +1,4 @@ +% !TeX root = ../../thesis.tex \chapter{???Optimierung???} \label{ch:optimizing} diff --git a/chapters/thesis/chapter06.tex b/chapters/thesis/chapter06.tex index 25ba660..36dae62 100644 --- a/chapters/thesis/chapter06.tex +++ b/chapters/thesis/chapter06.tex @@ -1,3 +1,4 @@ +% !TeX root = ../../thesis.tex \chapter{Evaluierung} \label{ch:evaluation} diff --git a/frontbackmatter/thesis/Acronyms.tex b/frontbackmatter/thesis/Acronyms.tex index ae79e31..a37aa6c 100644 --- a/frontbackmatter/thesis/Acronyms.tex +++ b/frontbackmatter/thesis/Acronyms.tex @@ -1,3 +1,5 @@ +% !TeX root = ../../thesis.tex + %******************************************************* % Acronyms %******************************************************* @@ -22,9 +24,11 @@ \acro{CSS}{Cascading Style Sheets} \acro{SFSB}{Stateful Session-Bean} \acro{JPA}{Java Persistence API} + \acro{JPQL}{Java Persistence Query Language} \acro{API}{Application Programming Interface} \acro{UML}{Unified Modeling Language} \acro{GB}{Gigabyte} + \acro{SQL}{Structured Query Language} \end{acronym} \cleardoublepage diff --git a/thesis.pdf b/thesis.pdf index 67676dc..0678e22 100644 Binary files a/thesis.pdf and b/thesis.pdf differ