diff --git a/thesis-beamer.pdf b/thesis-beamer.pdf index e7299fb..3442eeb 100644 Binary files a/thesis-beamer.pdf and b/thesis-beamer.pdf differ diff --git a/thesis-beamer.tex b/thesis-beamer.tex index 5a2e956..aa1ac56 100644 --- a/thesis-beamer.tex +++ b/thesis-beamer.tex @@ -6,17 +6,41 @@ \input{marco-galster-config} \addbibresource{expose-ref.bib} +%\usepackage{fourier} +\usepackage{array} +\usepackage{makecell} +\renewcommand\theadalign{bc} +\renewcommand\theadfont{\bfseries} +\renewcommand\theadgape{\Gape[4pt]} +\renewcommand\cellgape{\Gape[4pt]} + % ACHTUNG: Damit sich die Datei sauber im Visual Studio Code übersetzten lässt, muss in den Benutzer-Einstellungen % das Element "latex-workshop.latex.tools" aufgenommen werden und der erscheinende Eintrag für latexmk bei den % args am Anfang um den folgenden Eintrage erweitert werden: % "-shell-escape" +% TODO + \title{\myTitle} %\subtitle{} \author[M. Galster]{\myName} -\footlinetext{\insertshortauthor \hspace{4em} Multi-Layer Optimization Strategies for Enhanced Performance in Digital Editions} +\footlinetext{\insertshortauthor \hspace{4em} Multi"=Layer Optimization Strategies for Enhanced Performance in Digital Editions} \institute{Universität~in~Hagen,~Deutschland} -\date{\myTime} +\date{07. November 2024} + +\tikzset{ + every axis/.style={ + %%width=\textwidth,height=\textheight, + xlabel={Aufruf}, + ylabel={Laufzeit [ms]}, + enlargelimits=0.05, + ymin=0, %ymax=2100, + xtick={0,1,2,3,4,5}, %Ticks explizit angeben, dass bei grpßerer Darstellung nicht Zwischenticks existieren + legend pos=north east, + ymajorgrids=true, + grid style=dashed, + }, +} \begin{document} \selectlanguage{ngerman} @@ -26,13 +50,15 @@ % und dort markieren, was genau verändert wurde % -- SLIDE -- Title +% 1. Titelfolie \begin{frame}[plain] \titlepage \end{frame} % -- SLIDE -- TOC +% 2. Agenda \begin{frame}[c] - \frametitle{Übersicht} + \frametitle{Agenda} %left space \begin{addmargin*}{2.5em} @@ -50,7 +76,8 @@ \def\showHorizontalNavBar{True} % -- SLIDES -- -\section{Übersicht} +% 3. Einleitung (Warum ist das Thema relevant, Ziel der Arbeit, Ergebnis mit dem nicht gerechnet hat) +\section{Einleitung} \begin{frame}[c] \frametitle{Problemstellung} \begin{columns} @@ -67,6 +94,7 @@ \end{columns} \end{frame} +% 4. Forschungsgegenstand (Thema einführen durch Vorstellung Forschungsgegenstand) \begin{frame}[c] \frametitle{Ablauf einer Web-Anfrage} \begin{figure}[centered] @@ -84,7 +112,7 @@ \node (JPA) [block,below of=EJB] {Java Persistance API}; \node (openJPA) [block, below of=JPA] {OpenJPA Cache}; \node (fitGlassfish) [rounded corners,fit=(JSF) (EJB) (JPA) (openJPA)] {}; - \node [left] at (fitGlassfish.west) [text width=1.5cm] {Glassfish/ Payara}; + \node [left] at (fitGlassfish.west) [text width=1.5cm] {GlassFish/ Payara}; \node (memoryBuffers) [block, below of=openJPA] {Memory Buffers}; \node (services) [block, right of=memoryBuffers, xshift=2cm] {Services}; @@ -107,114 +135,352 @@ \end{figure} \end{frame} -\section{Untersuchungen} +\begin{frame}[c] + \frametitle{Anpassungen} + \begin{columns} + \column{0.5\textwidth} + \onslide<1>{ + \begin{itemize} + \item Caching EJB + \end{itemize} + } + \onslide<2>{ + \begin{itemize} + \item Abfragen in JPQL + \item Abfragen in Criteria API + \end{itemize} + } + \onslide<3>{ + \begin{itemize} + \item Caching in OpenJPA + \item Cached Queries + \item Caching mit Ehcache + \end{itemize} + } + \onslide<4>{ + \begin{itemize} + \item Materialized Views + \item Optimierung der Abfrage + \end{itemize} + } + + + \column{0.5\textwidth} + \begin{figure}[centered] + \begin{tikzpicture}[scale=.55,transform shape,node distance=4em, + block/.style={rectangle, rounded corners,minimum width=3cm,minimum height=.5cm,text centered, draw=black,fill=green!30}, + selected/.style={rectangle, rounded corners,minimum width=3cm,minimum height=.5cm,text centered, draw=black,fill=blue!30}, + halfselected/.style={rectangle, rounded corners,minimum width=3cm,minimum height=.5cm,text centered, draw=black,fill=blue!15}, + lineArrow/.style={arrows={-Latex[length=5pt 3 0]}}, + every fit/.style={inner sep=.4em,draw} + ] + \node (browser) [block] {Webbrowser}; + \node (fitClient) [rounded corners,fit=(browser)] {}; + \node [left] at (fitClient.west) {Client}; + + \onslide<4>{\node (JSF) [halfselected,below of=browser,node distance=5em] {Java Server Faces};} + \onslide<1-3>{\node (JSF) [block,below of=browser,node distance=5em] {Java Server Faces};} + \onslide<1>{\node (EJB) [selected,below of=JSF] {Enterprise Java Beans};} + \onslide<2-4>{\node (EJB) [block,below of=JSF] {Enterprise Java Beans};} + \onslide<2>{\node (JPA) [selected,below of=EJB] {Java Persistance API};} + \onslide<1,3,4>{\node (JPA) [block,below of=EJB] {Java Persistance API};} + \onslide<3>{\node (openJPA) [selected, below of=JPA] {OpenJPA Cache};} + \onslide<1,2,4>{\node (openJPA) [block, below of=JPA] {OpenJPA Cache};} + \node (fitGlassfish) [rounded corners,fit=(JSF) (EJB) (JPA) (openJPA)] {}; + \node [left] at (fitGlassfish.west) [text width=1.5cm] {GlassFish/ Payara}; + + \node (memoryBuffers) [block, below of=openJPA] {Memory Buffers}; + \node (services) [block, right of=memoryBuffers, xshift=2cm] {Services}; + \onslide<4>{\node (database) [selected, below of=memoryBuffers] {Database};} + \onslide<1-3>{\node (database) [block, below of=memoryBuffers] {Database};} + \node (fitPostgreSQL) [rounded corners,fit=(memoryBuffers) (services) (database)] {}; + \node [left] at (fitPostgreSQL.west) {PostgreSQL}; + + \node (fitServer) [rounded corners,fit=(fitGlassfish) (fitPostgreSQL),inner xsep=3em] {}; + \node [left] at (fitServer.west) {Server}; + + \draw[lineArrow] (browser)--(JSF); + \draw[lineArrow] (JSF)--(EJB); + \draw[lineArrow] (EJB)--(JPA); + \draw[lineArrow] (JPA)--(openJPA); + \draw[lineArrow] (openJPA)--(memoryBuffers); + \draw[lineArrow] (memoryBuffers)--(database); + \draw[lineArrow] (services)|-(database); + \end{tikzpicture} + %\label{fig:webrequest} + \end{figure} + \end{columns} +\end{frame} + +% 5. Methodik +\section{Methodik} +\begin{frame}[c] + \frametitle{Voraussetzungen} + \begin{itemize} + \item Verwendung von Docker, zur Performance"=Limitierung + \item Eigene Container für die Datenbank und den Webserver + \item Für die Untersuchung wird nur die Dokumentenliste beobachtet + \item Verwendung von Scripts zur besseren Vergleichbarkeit und Wiederholgenauigkeit + \end{itemize} +\end{frame} + \begin{frame}[c] \frametitle{Vorgehen} \begin{itemize} \item Vor jeder Messung werden die Container neugestartet und die Startroutinen abgewartet - \item Aufruf eines Bash-Script auf dem gleichen Rechner wie die Docker-Container um die Latenz des Netzwerkes auszuschließen + \item Aufruf eines Bash"=Script auf dem gleichen Rechner wie die Docker-Container um die Latenz des Netzwerkes auszuschließen \item Ermittlung des Speicherbedarfs vor und nach dem Webseitenaufrufen - \item Messung der Aufruf der Index-Seite (ohne Datenbankaufrufe) und der Dokumentenliste, jeweils 10 mal - \item Report über die SQL-Abfragen mit pgBadger erstellen + \item Messung der Aufruf der Index"=Seite (ohne Datenbankaufrufe) und der Dokumentenliste, jeweils 10 mal + \item Report über die SQL"=Abfragen mit pgBadger erstellen \end{itemize} \end{frame} \begin{frame}[c] - \frametitle{Voraussetzungen} + \frametitle{Erste Auffäligkeiten} \begin{itemize} - \item Verwendung von Docker, zur Performance-Limitierung - \item Eigene Container für die Datenbank und den Webserver - \item Für die Untersuchung wird nur die Dokumentenliste beobachtet - \end{itemize} - - \vspace{10pt} - Erste Auffälligkeiten - \begin{itemize} - \item OutOfMemory-Ausnahme ausgelöst nach dem vierten Script Aufruf ($\sim$40 Webseitenaufrufe) - \item Erhöhung des Java-Heapspeichers von 512MB auf 4096MB hat nur die Anzahl der Aufrufe bis zum Absturz verzögert + \item OutOfMemory"=Ausnahme ausgelöst nach dem vierten Script Aufruf ($\sim$40 Webseitenaufrufe) + \item Erhöhung des Java"=Heapspeichers von 512MB auf 4096MB hat nur die Anzahl der Aufrufe bis zum Absturz verzögert \end{itemize} \end{frame} -%\subsection{Ohne Cache} +\section{Untersuchungen} \begin{frame}[c] - \frametitle{Ohne Cache} + \frametitle{Vergleichsmessung - Ohne Cache} \begin{columns} - \onslide<2->{ - \column{0.5\textwidth} + \column{0.5\textwidth} + \begin{overprint} \begin{itemize} + \item Deaktivieren aller Caches \item Auffälliger Speicheranstieg, trotz deaktiviertem Cache \item Gleichmässige Anzahl an Datenbankabfragen \item Gleichmässige Laufzeit der Datenbankabfragen \item Laufzeitanteil der Datenbankabfragen unter 10\% \end{itemize} - } + \end{overprint} - \onslide<1->{ - \column{0.5\textwidth} - \begin{table}[h!] - \centering - \resizebox{\textwidth}{!}{ \begin{tabular}{r|r|r|r|r|r|r|r|r} - & \multicolumn{3}{c|}{Aufrufzeit (ms)} & \multicolumn{2}{c|}{Datenbankabfragen} & \multicolumn{3}{c}{Speicherverbrauch (MB)} \\ - \# & min & avg & max & \#-avg & avg (ms) & davor & danach & diff \\ - \hline - \hline - 1 & 360 & 623 & 2079 & 1224.0 & 30.3 & 872.8 & 914.1 & 41.3 \\ % 12240 - 303 ms (135+ 79+ 39+ 22+17+11) (#2-6,8) - 2 & 331 & 372 & 430 & 1208.0 & 31.2 & 914.5 & 1008.0 & 93.5 \\ % 24320 - 615 ms (270+156+ 78+ 56+34+21) (#2-7) - 3 & 291 & 428 & 815 & 1208.0 & 33.5 & 1030.0 & 1297.0 & 267.0 \\ % 36400 - 950 ms (406+256+118+ 79+55+36) (#2-7) - \textbf{4} & 288 & 357 & 433 & 1208.0 & 33.7 & 1299.0 & 1461.0 & 162.0 \\ % 48480 - 1287 ms (564+334+167+105+72+45) (#2-7) - 5 & 294 & 404 & 499 & 1208.0 & 32.9 & 1462.0 & 1638.0 & 176.0 \\ % 60560 - 1616 ms (699+428+210+128+92+59) (#2-7) - \end{tabular} } - \caption{Messung ohne Caches} - \end{table} - } + \column{0.5\textwidth} + \centering + \resizebox{0.8\textwidth}{!}{ \begin{tabular}{r|r|r|r|r|r} + \thead{\#} & \thead{Call \\ (ms)} & \thead{Query \\ (\# / ms)} & \thead{Memory \\ Diff (MB)} & \thead{Render \\ (ms)} & \thead{DB"=load \\ (ms)} \\ + \hline + \hline + 0 & 1931 & - & - & 1849 & 710 \\ + 1 & 682 & 1223.0 / 30.3 & 54.8 & 666 & 399 \\ + 2 & 389 & 1208.0 / 31.2 & 172.5 & 378 & 282 \\ + 3 & 407 & 1208.0 / 33.5 & 110.0 & 398 & 307 \\ + 4 & 359 & 1208.0 / 33.7 & 193.0 & 351 & 269 \\ + \textbf{5} & 317 & 1208.0 / 32.9 & 107.0 & 309 & 235 \\ + \end{tabular} } + + \vspace{10pt} + \begin{tikzpicture}[scale=0.2,every node/.style={scale=0.6}] + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,0) rectangle (31.7,1.5); % WebRequest + \draw[fill=orange] (0,1.5) rectangle (30.9,3); % Render + \draw[fill=yellow] (0,3) rectangle (23.5,4.5); % DB-Load + \draw[fill=green] (0,4.5) rectangle (3.3,6); % DB + % Beschriftungen hinzufügen + \node at (15.0, 0.7) {WebRequest}; + \node at (15.0, 2.2) {Render}; + \node at (15.0, 3.7) {DB"=Load}; + \node at (15.0, 5.2) {Queries}; + \end{tikzpicture} \end{columns} \end{frame} % Hier 2-3 der aktuellen erarbeiten Ansätze Vorstellen und nach dem Warum fragen % Genau beschreiben was Signifikant besser/schlechter ist +\begin{frame} + \frametitle{Caching EJB} + + \begin{itemize} + \item Konfiguration über die Webseite des Payara"=Servers + \item habt keine Auswirkungen auf die Performance + \item Der Cache wird nur von den Provider selbst und nicht den geladenen Datenbank"=Objekten verwendet + \end{itemize} + + \vspace{8pt} + \begin{corollary} + Nicht nutzbar für dieses Szenario + \end{corollary} +\end{frame} + +\begin{frame} + \frametitle{Abfragesprachen} + + \begin{itemize} + \item Ähnliche gemessene Zeiten + \item Untersuchung im Debugger zeigt ähnlicher Abfrage"=Syntax innerhalb von OpenJPA + \item Prüfung der SQL"=Abfragen zeigt, dass die identischen Befehle an die Datenbank übertragen werden + \item Keine Unterschied im Speicherverbrauch feststellbar + \item Gleiche Optimierung durch Hint \texttt{openjpa.FetchPlan.EagerFetchMode} (halbierte Laufzeit, geviertelte Datenbankaufrufe) + \item Andere Hints hatte keine messbaren Auswirkungen + \end{itemize} + + \vspace{8pt} + \begin{corollary} + Daher kann die Art der Programmierung verwendet werden die für den Anwendungsfall die einfachere ist + \end{corollary} +\end{frame} + %\subsection{OpenJPA-Cache} \begin{frame}[c] \frametitle{Caching mit OpenJPA} \begin{columns} - \onslide<2->{ - \column{0.5\textwidth} + \begin{column}{0.5\textwidth} + \begin{overprint} + + \onslide<1> + \begin{itemize} + \item Einfaches aktivieren + \item Direkte Unterstützung + \item Konfiguration über die Anzahl der Objekte + \item Messung mit 1000 und 10000 Objekten + \end{itemize} + + \onslide<2> \begin{itemize} \item Erwartete Reduzierung der Datenbankabfragen \item Laufzeit in der Datenbank halbiert sich nicht, trotz halbierter Abfragen \item Speicheranstieg wurde reduziert \end{itemize} - } + + \end{overprint} + \end{column} - \onslide<1->{ - \column{0.5\textwidth} - \begin{table}[h!] - \small - \centering - \resizebox{\textwidth}{!}{ \begin{tabular}{r|r|r|r|r|r|r|r|r} - & \multicolumn{3}{c|}{Aufrufzeit (ms)} & \multicolumn{2}{c|}{Datenbankabfragen} & \multicolumn{3}{c}{Speicherverbrauch (MB)} \\ - \# & min & avg & max & \#-avg & avg (ms) & davor & danach & diff \\ - \hline - \hline - ref-4 & 288 & 357 & 433 & 1208.0 & 33.7 & 1299.0 & 1461.0 & 162.0 \\ % 48480 - 1287 ms (564+334+167+105+72+45) (#2-7) - \hline - \hline - 1 & 338 & 567 & 1853 & 741.8 & 28.8 & 874.8 & 923.5 & 48.7 \\ % 7418 - 288 ms (145+ 42+ 40+ 24+18+ 8+ 7+ 4) (#2-8,12) - 2 & 235 & 290 & 460 & 685.2 & 25.8 & 923.5 & 926.4 & 2.9 \\ % 14270 - 546 ms (282+ 81+ 70+ 47+33+14+11+ 8) (#2-9) - 3 & 225 & 254 & 313 & 683.6 & 27.6 & 927.4 & 1018.0 & 90.6 \\ % 21106 - 822 ms (430+120+ 99+ 77+49+20+16+11) (#2-9) - 4 & 235 & 289 & 403 & 683.9 & 27.6 & 1018.0 & 1018.0 & 0.0 \\ % 27945 - 1098 ms (569+160+137+ 99+68+26+22+17) (#2-9) - 5 & 193 & 265 & 359 & 687.9 & 27.6 & 1025.0 & 1140.0 & 115.0 \\ % 34824 - 1374 ms (704+202+171+128+86+34+27+22) (#2-9) - \hline - \hline - 1 & 151 & 368 & 1904 & 142.2 & 20.8 & 878.1 & 919.9 & 41.8 \\ % 1422 - 208 ms (133+ 40+ 23+9+2+1) (#2,4-6,10,12) - 2 & 133 & 143 & 159 & 6.0 & 20.5 & 919.8 & 921.0 & 1.2 \\ % 1482 - 413 ms (274+ 80+ 47+9+2+1) (#2-3,5,6,10,12) - 3 & 120 & 126 & 132 & 6.0 & 19.9 & 922.8 & 924.1 & 1.3 \\ % 1542 - 612 ms (412+119+ 69+9+2+1) (#2,3,5,6,10,12) - 4 & 120 & 124 & 128 & 6.0 & 21.4 & 924.1 & 925.4 & 1.3 \\ % 1602 - 826 ms (550+168+ 96+9+2+1) (#2-4,6,10,12) - 5 & 109 & 114 & 131 & 6.0 & 19.7 & 926.1 & 926.8 & 0.7 \\ % 1662 - 1023 ms (683+209+119+9+2+1) (#2-4,6,10,12) - \end{tabular} } - \caption{Messung mit OpenJPA-Cache und Größe auf 1000 bzw. 10000} - \end{table} - } + % Rechte Spalte + \column{0.5\textwidth} + \center + \resizebox{0.8\textwidth}{!}{\begin{tabular}{r|r|r|r|r|r} + \thead{\#} & \thead{Call \\ (ms)} & \thead{Query \\ (\# / ms)} & \thead{Memory \\ Diff (MB)} & \thead{Render \\ (ms)} & \thead{DB"=load \\ (ms)} \\ + \hline + \hline + ref-5 & 317 & 1208.0 / 32.9 & 107.0 & 309 & 235 \\ + \hline + \hline + 0 & 2347 & - & - & 2286 & 770 \\ + 1 & 611 & 730.2 / 28.8 & 39.2 & 595 & 284 \\ + %2 & 319 & 667.3 / 25.8 & 117.3 & 309 & 195 \\ + 3 & 281 & 680.6 / 27.6 & 56.0 & 271 & 180 \\ + %4 & 280 & 671.3 / 27.6 & 55.0 & 271 & 189 \\ + 5 & 272 & 683.6 / 27.6 & 97.0 & 264 & 175 \\ + \hline + \hline + 0 & 1904 & - & - & 2232 & 847 \\ + 1 & 368 & 141.2 / 20.8 & 30.5 & 404 & 124 \\ + %2 & 143 & 6.0 / 20.5 & 3.6 & 136 & 36 \\ + 3 & 126 & 6.0 / 19.9 & 3.3 & 136 & 47 \\ + %4 & 124 & 6.0 / 21.4 & 1.1 & 113 & 39 \\ + \textbf{5} & 114 & 6.0 / 19.7 & 1.2 & 107 & 32 \\ + \end{tabular} } + + \vspace{8pt} + \begin{tikzpicture}[scale=0.2,every node/.style={scale=0.6}] + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,7) rectangle (31.7,8.5); % WebRequest + \draw[fill=orange] (0,8.5) rectangle (30.9,10); % Render + \draw[fill=yellow] (0,10) rectangle (23.5,11.5); % DB-Load + \draw[fill=green] (0,11.5) rectangle (3.3,13); % DB + % Beschriftungen hinzufügen + \node at (15.0, 7.7) {ref"=Call}; + \node at (15.0, 9.2) {ref"=Render}; + \node at (15.0, 10.7) {ref"=DB"=Load}; + \node at (15.0, 12.2) {ref"=Queries}; + + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,0) rectangle (11.4,1.5); % WebRequest + \draw[fill=orange] (0,1.5) rectangle (10.7,3); % Render + \draw[fill=yellow] (0,3) rectangle (3.2,4.5); % DB-Load + \draw[fill=green] (0,4.5) rectangle (2.0,6); % DB + % Beschriftungen hinzufügen + \node at (7.0, 0.7) {Call}; + \node at (7.0, 2.2) {Render}; + \node at (7.0, 3.7) {DB"=Load}; + \node at (7.0, 5.2) {Queries}; + \end{tikzpicture} + \end{columns} +\end{frame} + +\begin{frame}[c] + \frametitle{Cached Queries} + \begin{itemize} + \item Einfaches aktivieren + \item Einzelne Abfragen können ausgeschlossen werden + \item Keine Auswirkung auf die Performance + \item Wird nur beachtet wenn keine Argumente vorhanden sind + \end{itemize} + + \vspace{8pt} + \begin{corollary} + Nur gut verwendbar, wenn keine Bedingungen vorhanden sind + \end{corollary} +\end{frame} + +\begin{frame}[c] + \frametitle{Caching mit Ehcache} + \begin{columns} + \column{0.5\textwidth} + \begin{overprint} + \onslide<1> + \begin{itemize} + \item Benötigt zusätzliche Pakete + \item Aufwendigere Konfiguration, ohne Fehlerausgabe + \item Zusätzliche Konfiguration bzw. Code zum aktivieren des Caches + \item Weitere Konfiguration an den Klassen möglich + \end{itemize} + + \onslide<2> + \begin{itemize} + \item Erwartete Reduzierung der Datenbankabfragen + \item Laufzeit der Datenbankabfragen halbiert sich nur trotz signifikant weniger Abfragen + \item Starke Reduzierung der Laderoutine von Datenbank nach Java"=Objekten + \item Geringer Speicheranstieg trotz des Caches + \item Sehr effizienter Cache, auch bei größeren Datenmengen + \end{itemize} + \end{overprint} + + \column{0.5\textwidth} + \centering + \resizebox{\textwidth}{!}{\begin{tabular}{r|r|r|r|r|r} + \thead{\#} & \thead{Call \\ (ms)} & \thead{Query \\ (\# / ms)} & \thead{Memory \\ Diff (MB)} & \thead{Render \\ (ms)} & \thead{DB"=load \\ (ms)} \\ + \hline + \hline + ref-5 & 317 & 1208.0 / 32.9 & 107.0 & 309 & 235 \\ + \hline + \hline + 0 & 2820 & - & - & 2809 & 1186 \\ + 1 & 488 & 135.2 / 20.7 & 24.4 & 490 & 175 \\ + 2 & 144 & 6.0 / 20.1 & 1.0 & 136 & 38 \\ + 3 & 129 & 6.0 / 19.4 & 1.0 & 121 & 34 \\ + 4 & 123 & 6.0 / 19.7 & 8.0 & 116 & 33 \\ + \textbf{5} & 118 & 6.0 / 12.7 & 4.0 & 111 & 34 \\ + \end{tabular} } + + \vspace{10pt} + \begin{tikzpicture}[scale=0.2,every node/.style={scale=0.6}] + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,7) rectangle (31.7,8.5); % WebRequest + \draw[fill=orange] (0,8.5) rectangle (30.9,10); % Render + \draw[fill=yellow] (0,10) rectangle (23.5,11.5); % DB-Load + \draw[fill=green] (0,11.5) rectangle (3.3,13); % DB + % Beschriftungen hinzufügen + \node at (15.0, 7.7) {ref"=Call}; + \node at (15.0, 9.2) {ref"=Render}; + \node at (15.0, 10.7) {ref"=DB"=Load}; + \node at (15.0, 12.2) {ref"=Queries}; + + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,0) rectangle (11.8,1.5); % WebRequest + \draw[fill=orange] (0,1.5) rectangle (11.1,3); % Render + \draw[fill=yellow] (0,3) rectangle (3.4,4.5); % DB-Load + \draw[fill=green] (0,4.5) rectangle (1.3,6); % DB + % Beschriftungen hinzufügen + \node at (6.0, 0.7) {Call}; + \node at (6.0, 2.2) {Render}; + \node at (6.0, 3.7) {DB"=Load}; + \node at (6.0, 5.2) {Queries}; + \end{tikzpicture} \end{columns} \end{frame} @@ -222,111 +488,290 @@ \begin{frame}[c] \frametitle{Abfragen über materialized views} \begin{columns} - \onslide<2->{ - \column{0.5\textwidth} + \column{0.5\textwidth} + \begin{overprint} + \onslide<1> \begin{itemize} - \item Deutliche Reduzierung der Datenbankabfragen und \=laufzeiten - \item Unter-Abfragen werden als Json-Objekte direkt hinterlegt + \item Materialized View und Webseite aus dem aktuellen Wedekind"=Projekt übernommen \citep{Dokument53:online} + \item Zusätzliche Anpassung an der View um die Parameter in der Abfrage zu entfernen für Test mit QueryCache + \item Verschiebung des JSON"=Parsen in den Webclient + \end{itemize} + + \onslide<2> + \begin{itemize} + \item Deutliche Reduzierung der Datenbankabfragen und "=laufzeiten + \item Unter"=Abfragen werden als JSON"=Objekte direkt hinterlegt \item Teuer beim erstellen, aber selten notwendig \item Geringe Schwankung der Aufrufzeiten \item Anteil der Datenbank nochmals reduziert + \item Deutliche Reduzierung der DB"=Load Laufzeit durch Verschiebung des JSON"=Parsing \end{itemize} - } + \end{overprint} - \onslide<1->{ - \column{0.5\textwidth} - \begin{table} - \centering - \resizebox{\textwidth}{!}{ \begin{tabular}{r|r|r|r|r|r|r|r|r} - & \multicolumn{3}{c|}{Aufrufzeit (ms)} & \multicolumn{2}{c|}{Datenbankabfragen} & \multicolumn{3}{c}{Speicherverbrauch (MB)} \\ - \# & min & avg & max & \#-avg & avg (ms) & davor & danach & diff \\ - \hline - \hline - ref & 288 & 357 & 433 & 1208.0 & 33.7 & 1299.0 & 1461.0 & 162.0 \\ % 48480 - 1287 ms (564+334+167+105+72+45) (#2-7) - \hline - \hline - 1 & 203 & 315 & 808 & 17.8 & 3.0 & 851.4 & 883.9 & 32.5 \\ % 178 - 30 ms (19+11+0) (#2,4,8) - 2 & 154 & 172 & 187 & 9.0 & 2.2 & 883.2 & 887.0 & 3.8 \\ % 268 - 52 ms (33+18+1) (#2,3,8) - 3 & 145 & 151 & 163 & 9.0 & 2.8 & 887.7 & 895.3 & 7.6 \\ % 358 - 80 ms (52+27+1) (#2,3,8) - 4 & 132 & 143 & 152 & 9.0 & 2.8 & 896.0 & 900.0 & 4.0 \\ % 448 - 108 ms (70+37+1) (#2,3,8) - 5 & 121 & 125 & 132 & 9.0 & 2.4 & 900.6 & 901.0 & 0.4 \\ % 538 - 132 ms (85+46+1) (#2,3,8) - \end{tabular} } - \caption{Messung mit Materialized View} - \end{table} - } + \column{0.5\textwidth} + \centering + \resizebox{\textwidth}{!}{\begin{tabular}{r|r|r|r|r|r} + \thead{\#} & \thead{Call \\ (ms)} & \thead{Query \\ (\# / ms)} & \thead{Memory \\ Diff (MB)} & \thead{Render \\ (ms)} & \thead{DB"=load \\ (ms)} \\ + \hline + \hline + ref-5 & 317 & 1208.0 / 32.9 & 107.0 & 309 & 235 \\ + \hline + \hline + 0 & 859 & - & - & 803 & 334 \\ + 1 & 348 & 16.8 / 2.5 & 36.4 & 331 & 174 \\ + 2 & 194 & 9.0 / 2.4 & 2.6 & 185 & 99 \\ + 3 & 161 & 9.0 / 2.4 & 3.0 & 152 & 77 \\ + 4 & 145 & 9.0 / 2.4 & -3.4 & 137 & 73 \\ + 5 & 137 & 9.0 / 2.4 & 3.0 & 129 & 72 \\ + \textbf{js} & 70+13 & 9.0 / 2.4 & - & $\sim$60 & 4 \\ + \end{tabular} } + + \vspace{8pt} + \begin{tikzpicture}[scale=0.2,every node/.style={scale=0.6}] + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,7) rectangle (31.7,8.5); % WebRequest + \draw[fill=orange] (0,8.5) rectangle (30.9,10); % Render + \draw[fill=yellow] (0,10) rectangle (23.5,11.5); % DB-Load + \draw[fill=green] (0,11.5) rectangle (3.3,13); % DB + % Beschriftungen hinzufügen + \node at (15.0, 7.7) {ref"=Call}; + \node at (15.0, 9.2) {ref"=Render}; + \node at (15.0, 10.7) {ref"=DB"=Load}; + \node at (15.0, 12.2) {ref"=Queries}; + + % Zeichne die Balken von unten nach oben (9) + \draw[fill=red] (0,0) rectangle (8.3,1.5); % WebRequest + \draw[fill=orange] (0,1.5) rectangle (6,3); % Render + \draw[fill=yellow] (0,3) rectangle (0.4,4.5); % DB-Load + \draw[fill=green] (0,4.5) rectangle (0.3,6); % DB + % Zeichne die Balken von unten nach oben (5) + %\draw[fill=red] (0,0) rectangle (13.7,1.5); % WebRequest + %\draw[fill=orange] (0,1.5) rectangle (12.9,3); % Render + %\draw[fill=yellow] (0,3) rectangle (7.2,4.5); % DB-Load + %\draw[fill=green] (0,4.5) rectangle (0.3,6); % DB + % Beschriftungen hinzufügen + \node at (3.0, 0.7) {Complete}; + \node at (3.0, 2.2) {Server"=Side}; + \node at (3.0, 3.7) {DB"=Load}; + \node at (3.0, 5.2) {Queries}; + \end{tikzpicture} \end{columns} \end{frame} -\section{Vergleich} +\begin{frame}[c] + \frametitle{Optimierung der Abfrage} + \begin{columns} + \column{0.5\textwidth} + \begin{overprint} + \onslide<1> + \begin{itemize} + \item Große Datenmenge vom ersten Befehlt bis fast zur Ausgabe + \item Höchste Kosten im Seq Scan der Dokumententabelle + \item Nur Seq Scan bei den verlinkten Tabellen + \item Am Ende ist ein teurer Sort notwendig + \end{itemize} + + \onslide<2> + \begin{itemize} + \item Umstellung mit dem WITH"=Statement + \item Große Datenmenge verschwindet nach dem ersten Hash join + \item Verwendung von Index Scan + \item Kosten der Sortierung am Ende reduziert + \item Reduktion der Laufzeit um den Faktor drei + \item Nur möglich wenn die Bedingen ins WITH eingetragen werden können + \end{itemize} + \end{overprint} + + \column{0.5\textwidth} + \begin{overprint} + \onslide<1> + \includegraphics[width=\textwidth]{gfx/chapter05_ExplainVisualize.png} + + \onslide<2> + \includegraphics[width=\textwidth]{gfx/chapter05_ExplainVisualize_with.png} + \end{overprint} + \end{columns} +\end{frame} + +\section{Fazit} \begin{frame}[c] \frametitle{Vergleich} \begin{columns} - \column{0.3\textwidth} + \column{0.5\textwidth} \centering \begin{tikzpicture}[scale=.4] - \centering \begin{axis}[ title={Laufzeitvergleich Webseitenaufrufe}, - %width=\textwidth,height=\textheight, - xlabel={Aufruf}, - ylabel={Laufzeit [ms]}, - enlargelimits=0.05, - ymin=0, ymax=2100, - xtick={0,1,2,3,4,5}, %Ticks explizit angeben, dass bei grpßerer Darstellung nicht Zwischenticks existieren - ytick={0,500,1000,1500,2000,2500}, - legend pos=north east, - ymajorgrids=true, - grid style=dashed, + ymax=1200, ] - \addplot coordinates { (0,2079)(1,623)(2,372)(3,428)(4,357)(5,404) }; - \addplot coordinates { (0,1853) (1,567)(2,290)(3,254)(4,289)(5,265)}; - \addplot coordinates { (0,1904) (1,143)(2,126)(3,126)(4,124)(5,114)}; - \addplot coordinates { (0,808) (1,315)(2,172)(3,151)(4,143)(5,125)}; - \legend{Ohne Cache,OpenJPA Cache,OpenJPA Cache groß,Materialized View} + \addplot coordinates {(0,1931) (1,682)(2,389)(3,407)(4,359)(5,317)}; + \addplot coordinates {(0,2347) (1,611)(2,319)(3,281)(4,280)(5,272)}; + \addplot coordinates {(0,1904) (1,368)(2,143)(3,126)(4,124)(5,114)}; + \addplot coordinates {(0,2820) (1,488)(2,144)(3,129)(4,123)(5,118)}; + \addplot coordinates {(0, 859) (1,348)(2,194)(3,161)(4,145)(5,137)}; + \addplot coordinates {(5, 83)}; + \legend{Ohne Cache,OpenJPA Cache,OpenJPA Cache groß,Ehcache,Materialized View,Materialized View JS} \end{axis} \end{tikzpicture} - \begin{tikzpicture}[scale=.4] \centering + \begin{tikzpicture}[scale=.4] \begin{axis}[ title={Laufzeitvergleich Datenbankabfragen}, - %width=\textwidth,height=\textheight, - xlabel={Aufruf}, - ylabel={Laufzeit [ms]}, - enlargelimits=0.05, - ymin=0, ymax=60, + ymax=80, xtick={1,2,3,4,5}, %Ticks explizit angeben, dass bei grpßerer Darstellung nicht Zwischenticks existieren - legend pos=north east, - ymajorgrids=true, - grid style=dashed, ] - \addplot coordinates { (1,30.3)(2,31.5)(3,33.5)(4,33.7)(5,32.9) }; - \addplot coordinates { (1,28.8)(2,25.8)(3,27.6)(4,27.6)(5,27.6) }; - \addplot coordinates { (1,20.8)(2,20.5)(3,19.9)(4,21.4)(5,19.7) }; - \addplot coordinates { (1,3.0)(2,2.2)(3,2.8)(4,2.8)(5,2.4) }; - \legend{Ohne Cache,OpenJPA Cache,OpenJPA Cache groß,Materialized View} + \addplot coordinates {(1,30.3)(2,31.5)(3,33.5)(4,33.7)(5,32.9)}; + \addplot coordinates {(1,28.8)(2,25.8)(3,27.6)(4,27.6)(5,27.6)}; + \addplot coordinates {(1,20.8)(2,20.5)(3,19.9)(4,21.4)(5,19.7)}; + \addplot coordinates {(1,20.7)(2,20.1)(3,19.4)(4,19.7)(5,12.7)}; + \addplot coordinates {(1, 2.5)(2, 2.4)(3, 2.4)(4, 2.4)(5, 2.4)}; + \addplot coordinates {(5, 2.4)}; + \legend{Ohne Cache,OpenJPA Cache,OpenJPA Cache groß,Ehcache,Materialized View,Materialized View JS} \end{axis} \end{tikzpicture} - \pause + \column{0.5\textwidth} + \centering + \begin{tikzpicture}[scale=.4] + \begin{axis}[ + title={Laufzeitvergleich Render}, + ymax=1200, + ] + \addplot coordinates {(0,1849) (1,666)(2,378)(3,398)(4,351)(5,309)}; + \addplot coordinates {(0,2286) (1,595)(2,309)(3,271)(4,271)(5,264)}; + \addplot coordinates {(0,2232) (1,404)(2,136)(3,136)(4,113)(5,107)}; + \addplot coordinates {(0,2809) (1,490)(2,136)(3,121)(4,116)(5,111)}; + \addplot coordinates {(0, 803) (1,331)(2,185)(3,152)(4,137)(5,129)}; + \addplot coordinates {(5, 60)}; + \legend{Ohne Cache,OpenJPA Cache,OpenJPA Cache groß,Ehcache,Materialized View,Materialized View JS} + \end{axis} + \end{tikzpicture} - \column{0.7\textwidth} + \centering + \begin{tikzpicture}[scale=.4] + \begin{axis}[ + title={Laufzeitvergleich DB"=Load}, + ymax=1200, + ] + \addplot coordinates {(0, 710) (1,399)(2,282)(3,307)(4,269)(5,235)}; + \addplot coordinates {(0, 770) (1,284)(2,195)(3,180)(4,189)(5,175)}; + \addplot coordinates {(0, 847) (1,124)(2, 36)(3, 47)(4, 39)(5, 32)}; + \addplot coordinates {(0,1186) (1,175)(2, 38)(3, 34)(4, 33)(5, 34)}; + \addplot coordinates {(0, 334) (1,174)(2, 99)(3, 77)(4, 73)(5, 72)}; + \addplot coordinates {(5, 4)}; + \legend{Ohne Cache,OpenJPA Cache,OpenJPA Cache groß,Ehcache,Materialized View,Materialized View JS} + \end{axis} + \end{tikzpicture} + \end{columns} +\end{frame} + +\begin{frame} + \frametitle{Vergleich der besten Laufzeiten} + \begin{columns} + \column{0.5\textwidth} + \begin{tikzpicture}[scale=0.2,every node/.style={scale=0.6}] + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,26) rectangle (31.7,27.5); % WebRequest + \draw[fill=orange] (0,27.5) rectangle (30.9,29); % Render + \draw[fill=yellow] (0,29) rectangle (23.5,30.5); % DB-Load + \draw[fill=green] (0,30.5) rectangle (3.3,32); % DB + % Beschriftungen hinzufügen + \node at (9.0, 26.7) {ref"=Call}; + \node at (9.0, 28.2) {ref"=Render}; + \node at (9.0, 29.7) {ref"=DB"=Load}; + \node at (9.0, 31.2) {ref"=Queries}; + %\node at (25.0, 28.8) {ohne Cache}; + + % OpenJPA + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,19.5) rectangle (11.4,21); % WebRequest + \draw[fill=orange] (0,21) rectangle (10.7,22.5); % Render + \draw[fill=yellow] (0,22.5) rectangle (3.2,24); % DB-Load + \draw[fill=green] (0,24) rectangle (2.0,25.5); % DB + % Beschriftungen hinzufügen + \node at (6.0, 20.2) {Call}; + \node at (6.0, 21.7) {Render}; + \node at (6.0, 23.2) {DB"=Load}; + \node at (6.0, 24.7) {Queries}; + \node at (25.0, 22.6) {OpenJPA 10000 Objekte}; + + % Ehcache + % Zeichne die Balken von unten nach oben + \draw[fill=red] (0,13) rectangle (11.8,14.5); % WebRequest + \draw[fill=orange] (0,14.5) rectangle (11.1,16); % Render + \draw[fill=yellow] (0,16) rectangle (3.4,17.5); % DB-Load + \draw[fill=green] (0,17.5) rectangle (1.3,19); % DB + % Beschriftungen hinzufügen + \node at (6.0, 13.7) {Call}; + \node at (6.0, 15.2) {Render}; + \node at (6.0, 16.7) {DB"=Load}; + \node at (6.0, 18.2) {Queries}; + \node at (25.0, 15.8) {Ehcache}; + + % matview normal + % Zeichne die Balken von unten nach oben (5) + \draw[fill=red] (0,6.5) rectangle (13.7,8); % WebRequest + \draw[fill=orange] (0,8) rectangle (12.9,9.5); % Render + \draw[fill=yellow] (0,9.5) rectangle (7.2,11); % DB-Load + \draw[fill=green] (0,11) rectangle (0.3,12.5); % DB + \node at (3.0, 7.2) {Call}; + \node at (3.0, 8.7) {Render}; + \node at (3.0, 10.2) {DB"=Load}; + \node at (3.0, 11.7) {Queries}; + \node at (25.0, 9.3) {Materialized View}; + + % matview parseJson Client + % Zeichne die Balken von unten nach oben (9) + \draw[fill=red] (0,0) rectangle (8.3,1.5); % WebRequest + \draw[fill=orange] (0,1.5) rectangle (6,3); % Render + \draw[fill=yellow] (0,3) rectangle (0.4,4.5); % DB-Load + \draw[fill=green] (0,4.5) rectangle (0.3,6); % DB + % Beschriftungen hinzufügen + \node at (3.0, 0.7) {Complete}; + \node at (3.0, 2.2) {Server"=Side}; + %\node at (3.0, 0.7) {Call}; + %\node at (3.0, 2.2) {Render}; + \node at (3.0, 3.7) {DB"=Load}; + \node at (3.0, 5.2) {Queries}; + \node at (25.0, 2.8) {Materialized View Client"=Parsing}; + \end{tikzpicture} + + \column{0.5\textwidth} \begin{itemize} - \item Keine Start-Phase auf der Datenbank zu erkennen, im Gegensatz zur Anwendung \item Die Datenbankabfragen nehmen den kleinsten Teil der Laufzeit ein + \item Beim Großteil der Optimierung wird die Zeit bei DB"=Load verringert + \item Die Differenz zwischen DB"=Load und Render verändert sich gering + \item Hoher Offset im DB"=Load, außer bei Materialized View mit Client Parsing \item Materialized View geringste Datenbankabfragezeiten, aber nicht schneller als OpenJPA-Cache mit größerem Cache + %\item Die erhöhte Differenz bei zwischen Render und Call bei Materialized View mit Client Parsing ist der Client"=Anteil \end{itemize} \end{columns} + \end{frame} + +\begin{frame} + \frametitle{Zusammenfassung} + + \begin{itemize} + \item Query"=Cache und EJB"=Cache nicht verwendbar + \item Bei Verwendung von Cache auf Ehcache umstellen, OpenJPA"=Cache ist ineffizienter + \item Die Wahl der Abfragesprache hat keine Performance"=Beeinflussung + \item Verwendung der Materialized"=View mit JSON"=Parsing am Client hat die beste Performance + \item Abfragen können optimiert werden, aber besitzen nur geringe Auswirkung auf den gesamten Aufruf + \item Größtes Optimierungspotential im ORM vorhanden, bei der Bereitstellung der Entitäten (gut an der Umsetzung mit Materialized"=View zu sehen) + \end{itemize} + \end{frame} \begin{frame} \frametitle{Ausblick} \begin{itemize} - \item Größte Optimierungspotenziale sind in der Anwendung vorhanden - \item Ermittlung welcher Teil der Anwendung die meiste Zeit benötigt - \item Weitere Prüfung der anderen Caches - \item Suche des Speicherlecks + \item Weitestgehende optimale Umsetzung der Schichten im GlassFish"=Server, bzw. wenige Optimierungsmöglichkeiten + \item Verlagerung des Aufbaus der Darstellung an den Client um weniger Ressourcen am Server zu nutzen + \item Speicherleck im OpenJPA durch neue Version behebbar + \item Wechseln auf anderen ORM oder eigene Entwicklung + \item Verwendung von Caches benötigen zusätzliche Ressourcen, daher nicht sinnvoll bei schwächeren Serversystemen \end{itemize} \end{frame}