|
|
|
@ -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<Document> 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<Document> cq = cb.createQuery(Document.class);
|
|
|
|
|
Root<Document> from = cq.from(Document.class);
|
|
|
|
|
ParameterExpression<Boolean> includedPara = cb.parameter(Boolean.class, "published");
|
|
|
|
|
ParameterExpression<Date> validPart = cb.parameter(Date.class, "now");
|
|
|
|
|
|
|
|
|
|
CriteriaQuery<Document> select = cq.select(from)
|
|
|
|
|
.where(cb.and(
|
|
|
|
|
cb.equal(from.get("isPublishedInDb"), includedPara),
|
|
|
|
|
cb.greaterThan(from.get("validUntil"), validPart)
|
|
|
|
|
));
|
|
|
|
|
TypedQuery<Document> 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<Document> 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}
|
|
|
|
|
|
|
|
|
|