diff --git a/chapters/thesis/appendix04.tex b/chapters/thesis/appendix04.tex index 276594f..ea5bbb5 100644 --- a/chapters/thesis/appendix04.tex +++ b/chapters/thesis/appendix04.tex @@ -10,18 +10,17 @@ Um die Messungen etwas zu vereinfachen wurde ein Skript erstellt um die Aufrufe gesammelt durchzuführen. Um die Messungen durchzuführen werden die Befehl, wie in \ref{lst:calling_script_exec} dargestellt aufgerufen. -Durch die nummerierten Präfixe können im Nachgang über die \textit{pgBadger}"=Berichte die SQL-Abfragen verglichen -werden. Wichtig hierbei ist noch, dass vor dem ersten \textit{meascall}-Aufruf überprüft wird, ob die Docker-Container -gestartet und initialisiert sind. Wenn dies nicht der Fall ist, laufen die Abfragen ins leere. Am einfachsten ist das -über die Statistik von Docker zu ermitteln, ob die CPU-Auslastung auf einen niedrigen Level gefallen ist. +Durch die nummerierten Präfixe können im Nachgang über die \textit{pgBadger}"=Berichte die \ac{SQL}"=Abfragen verglichen +werden. Wichtig hierbei ist noch, dass vor dem \textit{measrun}-Aufruf überprüft wird, ob die Docker-Container +gestartet und initialisiert sind. Wenn dies nicht der Fall ist, laufen die Abfragen ins leere. Am einfachsten ist das, +wie dargestellt, über die Statistik von Docker zu ermitteln. Nun wird überwacht, das die CPU-Auslastung auf ein +niedriges Level fällt, danach kann das Skript für die Messung gerufen werden. \includecode[bash]{chapters/thesis/appendix04_calling_script.sh}{lst:calling_script}{Calling Script} \begin{lstlisting}[language=Bash,caption={Aufrufe des Unterstützungsscriptes},label=lst:calling_script_exec] callscript.sh measinit callscript.sh -rppf=_testname measres -callscript.sh -rppf=_testname meascall -callscript.sh -rppf=_testname -rppn=2 meascall -callscript.sh -rppf=_testname -rppn=3 meascall -callscript.sh -rppf=_testname -rppn=4 meascall +callscript.sh dcstats +callscript.sh -rppf=_testname measrun \end{lstlisting} \ No newline at end of file diff --git a/chapters/thesis/appendix04_calling_script.sh b/chapters/thesis/appendix04_calling_script.sh index 22435b9..e2753d7 100644 --- a/chapters/thesis/appendix04_calling_script.sh +++ b/chapters/thesis/appendix04_calling_script.sh @@ -12,6 +12,7 @@ script_path="/opt/docker/timing.sh" pgbadger_out="/opt/docker/pgreport" report_postfix="" report_postno="" +report_postmax="5" docker_name=dcpgbatch COMPOSE_FILE=/opt/docker/docker-compose.yaml @@ -20,14 +21,33 @@ gflog() { echo "follow the log: $domain_log" tail -f $domain_log } +gflogrm() { + echo "remove the log: $domain_log" + rm "$domain_log" +} gfconf() { nvim "$payara_config" } gfscript() { + gflogcount=$(cat "$domain_log" | wc -l) outPath=$pgbadger_out$report_postfix/bash.out touch "$outPath" + echo "" >>"$outPath" echo "============================================================" >>"$outPath" + echo "calling number $report_postno / $report_postmax" >>"$outPath" + echo "" >>"$outPath" bash $script_path | tee -a "$outPath" + gflastlog=$(cat "$domain_log" | wc -l) + gfcnt=$(($gflastlog - $gflogcount)) + printf "\n%-20s %+5s %+9s %+9s %+9s %+9s\n" "function" "Runs" "Min (ms)" "Avg (ms)" "Max (ms)" "1st (ms)" >>"$outPath" + + tail -$gfcnt $domain_log | awk '/PerformanceCounter-create \/view/ { print $3 }' | awk 'BEGIN {min=500;max=0} {sum += $1; cnt += 1}; first == "" { first = $1 }; min > $1 { min = $1 } max < $1 { max = $1 } END { if (cnt < 1) {cnt = -1}; printf("%-20s %5i %9.3f %9.3f %9.3f %9.3f\n", "view-create-list", cnt, min, sum/cnt, max, first) }' >>"$outPath" + tail -$gfcnt $domain_log | awk '/PerformanceCounter-build \/view/ { print $3 }' | awk 'BEGIN {min=500;max=0} {sum += $1; cnt += 1}; first == "" { first = $1 }; min > $1 { min = $1 } max < $1 { max = $1 } END { if (cnt < 1) {cnt = -1}; printf("%-20s %5i %9.3f %9.3f %9.3f %9.3f\n", "view-buildr-list", cnt, min, sum/cnt, max, first) }' >>"$outPath" + tail -$gfcnt $domain_log | awk '/PerformanceCounter-loadData \/view/ { print $3 }' | awk 'BEGIN {min=500;max=0} {sum += $1; cnt += 1}; first == "" { first = $1 }; min > $1 { min = $1 } max < $1 { max = $1 } END { if (cnt < 1) {cnt = -1}; printf("%-20s %5i %9.3f %9.3f %9.3f %9.3f\n", "view-loaddt-list", cnt, min, sum/cnt, max, first) }' >>"$outPath" + tail -$gfcnt $domain_log | awk '/PerformanceCounter-loadDataMap \/view/ { print $3 }' | awk 'BEGIN {min=500;max=0} {sum += $1; cnt += 1}; first == "" { first = $1 }; min > $1 { min = $1 } max < $1 { max = $1 } END { if (cnt < 1) {cnt = -1}; printf("%-20s %5i %9.3f %9.3f %9.3f %9.3f\n", "view-loaddm-list", cnt, min, sum/cnt, max, first) }' >>"$outPath" + tail -$gfcnt $domain_log | awk '/PerformanceCounter-renderData \/view/ { print $3 }' | awk 'BEGIN {min=500;max=0} {sum += $1; cnt += 1}; first == "" { first = $1 }; min > $1 { min = $1 } max < $1 { max = $1 } END { if (cnt < 1) {cnt = -1}; printf("%-20s %5i %9.3f %9.3f %9.3f %9.3f\n", "view-rdrdat-list", cnt, min, sum/cnt, max, first) }' >>"$outPath" + tail -$gfcnt $domain_log | awk '/PerformanceCounter-renderLoad \/view/ { print $3 }' | awk 'BEGIN {min=500;max=0} {sum += $1; cnt += 1}; first == "" { first = $1 }; min > $1 { min = $1 } max < $1 { max = $1 } END { if (cnt < 1) {cnt = -1}; printf("%-20s %5i %9.3f %9.3f %9.3f %9.3f\n", "view-rdrlst-list", cnt, min, sum/cnt, max, first) }' >>"$outPath" + tail -$gfcnt $domain_log | awk '/PerformanceCounter-render \/view/ { print $3 }' | awk 'BEGIN {min=500;max=0} {sum += $1; cnt += 1}; first == "" { first = $1 }; min > $1 { min = $1 } max < $1 { max = $1 } END { if (cnt < 1) {cnt = -1}; printf("%-20s %5i %9.3f %9.3f %9.3f %9.3f\n", "view-render-list", cnt, min, sum/cnt, max, first) }' >>"$outPath" } pginit() { @@ -68,9 +88,17 @@ pgrpres() { rm -R $pgbadger_out$report_postfix* fi } +pgrpout() { + echo "Show bash output" + outPath=$pgbadger_out$report_postfix/bash.out + cat "$outPath" +} dccreate() { sudo docker compose -f $COMPOSE_FILE create --force-recreate } +dcconf() { + nvim $COMPOSE_FILE +} dcstart() { sudo docker compose -f $COMPOSE_FILE start sleep 2 @@ -85,11 +113,24 @@ dcres() { dcstats() { sudo docker stats } +meascall() { + gfscript + pgrp + pglogrm +} +measrun() { + for i in $(seq 1 $report_postmax); do + report_postno=$i + meascall + done +} for name in "$@"; do case $name in -rppf=*) report_postfix="${name#*=}" ;; -rppn=*) report_postno="${name#*=}" ;; + -rppm=*) report_postmax="${name#*=}" ;; gflog) gflog ;; + gflogrm) gflogrm ;; gfconf) gfconf ;; gfscript) gfscript ;; gfrestart) pgrpinit ;; @@ -101,7 +142,9 @@ for name in "$@"; do pgrestart) pgrestart ;; pgrp) pgrp ;; pgrpres) pgrpres ;; + pgrpout) pgrpout ;; dcinit) dccreate ;; + dcconf) dcconf ;; dcstart) dcstart ;; dcstop) dcstop ;; dcres) dcres ;; @@ -110,6 +153,7 @@ for name in "$@"; do pginit pgrpres pglogrm 0 + gflogrm dccreate dcstart ;; @@ -117,15 +161,13 @@ for name in "$@"; do dcstop pgrpres pglogrm 0 + gflogrm dcstart pgrp pglogrm ;; - meascall) - gfscript - pgrp - pglogrm - ;; + meascall) meascall ;; + measrun) measrun ;; help) echo "CALLING: $0 [ ]" echo "The overview of the functions of this script." @@ -136,9 +178,11 @@ for name in "$@"; do echo "*** parameter ***" echo " -rppf= Postfix name for the report-folder (used by gfscript, pgrp, pgrpres, measres, meascall)" echo " -rppn= Postfix number for the report-folder (used by pgrp, measres, meascall)" + echo " -rppm= Count of calling meascall (used by measrun)" echo "" echo "*** glassfish ***" echo " gflog Show and follow the log of the glassfish server with $domain_name" + echo " gflogrm Remove the log file of the glassfish server with $domain_name" echo " gfconf Open the configuration file from glassfish server" echo " gfscript Calls the testscript for the website" echo "" @@ -150,19 +194,22 @@ for name in "$@"; do echo " pgconf Open the configuration file from postgresql" echo " pgrestart Restart the postgresql" echo " pgrp Generate the pgbadger report from postgresql log files" + echo " pgrpout Show the saved output of the bash scripts" echo " pgrpres Resetet the output of pgbadger" echo "" echo "*** docker ***" - echo " dcinit Docker erstellen" - echo " dcstart Docker Container starten" - echo " dcstop Docker Container stoppen" - echo " dcres Docker Container stoppen und loeschen" - echo " dcstats Docker live Statistik anzeigen" + echo " dcinit Create the both docker container" + echo " dcconf Open the configuration file for the docker container" + echo " dcstart Start the both docker container" + echo " dcstop Stop the both docker container stoppen" + echo " dcres Stop and remote the both docker container" + echo " dcstats Show the docker live statistik" echo "" echo "*** combine cmds ***" echo " measinit Initialize everthing after start" echo " measres reset data for new measuring" echo " meascall execute one measure" + echo " measrun execute calls of measure (default: 5 runs)" ;; *) echo >&2 "Invalid option $name" diff --git a/chapters/thesis/chapter03.tex b/chapters/thesis/chapter03.tex index 2fef937..fa70541 100644 --- a/chapters/thesis/chapter03.tex +++ b/chapters/thesis/chapter03.tex @@ -65,9 +65,9 @@ weitere Relationen notwendig sind. \includecode[SQL]{chapters/thesis/chapter03_documentlist.sql}{lst:documentlist}{Generische Abfrage der Dokumentenliste} \includecode[SQL]{chapters/thesis/chapter03_documentlist_sub.sql}{lst:documentlist_sub}{Sub-Abfrage pro Dokument} -Nach aktuellem Stand beinhaltet die Datenbank circa 5400 Briefe, für die jeweils 2-7 eingescannte Faksimile gespeichert -werden. Diese Graphik-Dateien werden im TIFF-Format abgespeichert und benötigen zwischen 1 und 80 MB Speicherplatz. -Dadurch kommt die Datenbank aktuell auf circa 3,8 GB. +Nach aktuellem Stand beinhaltet die Datenbank circa 5400 Briefe, für die jeweils zwei bis sieben eingescannte Faksimile +gespeichert werden. Diese Graphik-Dateien werden im TIFF-Format abgespeichert und benötigen zwischen 1 und 80 MB +Speicherplatz. Dadurch kommt die Datenbank aktuell auf circa 3,8 GB. Wie im Kapitel \ref{ch:basics} dargestellt, besteht die eigentliche Anwendung aus mehreren Schichten. Die PostgreSQL"=Schicht wurde schon im vorherigen Kapitel betrachtet. Daher gehen wir nun weiter nach oben in den Schichten diff --git a/chapters/thesis/chapter05.tex b/chapters/thesis/chapter05.tex index b5c19b4..63399c9 100644 --- a/chapters/thesis/chapter05.tex +++ b/chapters/thesis/chapter05.tex @@ -260,6 +260,8 @@ abfragt. \section{Caching im \ac{JPA}} \label{sec:performance-investigation-application:caching-jpa} +%hier ein test vom acf: \acf{JPA}. aber ich seh ihn nicht + \mytodos{muss noch umgebaut werden, falsche Konfiguration erwischt} %Die Cache-Einstellungen von \ac{JPA} werden über mehrere Einstellungen konfiguriert. Anhand von @@ -562,6 +564,30 @@ FROM document d LEFT JOIN sitecity sc ON sc.id = d.city_id; \end{lstlisting} +Zusätzlich werden noch einige Indexe hinzugefügt, für eine bessere Performance bei der Abfrage, wie in +\ref{lst:sql-materialized-view-index} zu sehen. + +\begin{lstlisting}[language=SQL,caption={SQL Materialized View},label=lst:sql-materialized-view-index] +CREATE INDEX idx_searchdocument_documentid + ON searchdocument (documentid); + +CREATE INDEX idx_searchdocument_author_surname_firstname + ON searchdocument ((author->>'surname'), (author->>'firstname')); + +CREATE INDEX idx_searchdocument_startdate + ON searchdocument (startyear, startmonth, startday); + +CREATE INDEX idx_searchdocument_addressees_first_entry + ON searchdocument + (((addressees->0->>'surname')::text), ((addressees->0->>'firstname')::text)); + +CREATE INDEX idx_searchdocument_city + ON searchdocument (city); + +CREATE INDEX idx_searchdocument_documentcategory + ON searchdocument (documentcategory); +\end{lstlisting} + % document, first/last, documentaddresseeperson, documentcoauthorperson, documentfacsimile und count % document, count, first/last \begin{table}[h!] @@ -601,8 +627,6 @@ WHERE d.validuntil > NOW() AND d.ispublishedindb = true; \end{lstlisting} -\mytodos{Die Indizies noch mit aufnehmen!} - Nach dem Anpassungen haben sich dann die Werte aus \ref{tbl:measure-materialized-view-ext} ergeben. \begin{table}[h!] @@ -643,6 +667,84 @@ dieser Wert zu klein oder groß definiert ist, wird die Laufzeit verschlechtert. Laufzeit der Datenbankanfrage auf circa 20 ms verlängert. Wenn der Wert zu gering gewählt ist, dann wird zwar die Laufzeit der Datenbankanfrage minimal verkürzt, aber die \textit{map}"=Funktion wird dadurch verlängert. +Das aktivieren der Cache-Optionen wie in \ref{sec:performance-investigation-application:caching-openjpa} oder in +\ref{sec:performance-investigation-application:caching-query} dargestellt, haben keine Auswirkung auf die Performance. +Dies ist dadurch erklärbar, da keine Objekte durch das OpenJPA"=Framework erstellt werden, sondern erst in der +\textit{map}"=Funktion des eigenen Codes. + +Nun wird noch geprüft, welche Performance das parsen der Json-Informationen im Server benötigt. Im ersten Schritt wird +die Parse-Funktion auskommentiert und die Seite nochmal aufgerufen. Durch diese Umstellung fällt die Laufzeit der +Datenermittlung auf circa 4 ms ab. Nun muss noch geprüft werden, welche Zeit nun der Client zum parsen der +\ac{Json}"=Daten benötigt. Hierfür werden die Daten in einem versteckten \textbf{span}"=Element hinterlegt, wie es im +Beispiel \ref{lst:jsf-datatable-json} zu sehen ist. Die hinterlegte \ac{CSS}"=Klasse ist zum auffinden der Elemente +für den späteren Javascript. Das \textbf{ajax}"=Element im Beispiel ist notwendig, damit bei einem Seitenwechsel die neu +übertragenen Elemente in eine lesbare Form gebracht werden. + +\begin{lstlisting}[language=xml,caption={DataTable mit Json},label=lst:jsf-datatable-json] + + + + + + + +\end{lstlisting} + +Um nun die übertragenen \ac{Json}"=Daten in eine darstellbare Form zu bringen, benötigt man noch eine +JavaScript"=Funktion. Diese Funktion \ref{lst:jsf-datatable-json-convert} wird ermittelt erst alle versteckten Elemente, +parsed den Inhalt und erstellt neue \ac{HTML}"=Elemente mit dem darzustellenden Inhalt. Zusätzlich wird noch eine +Zeitmessung mit eingebaut, um die Laufzeit am Client für das Rendern in der Konsole anzuzeigen. Die Funktion wird nun +direkt nach dem die Webseite fertig geladen wurde gerufen. + +\begin{lstlisting}[language=javascript,caption={Wandeln von Json nach Html},label=lst:jsf-datatable-json-convert] +function isEmpty(str) { + return (str === null) || (str === undefined) || (typeof str === "string" && str.length === 0); +} +function convertJsonData() { + let $jsonObj = $(".json-convert") + , start = new Date() + ; + + $.each($jsonObj, function() { + let json = this.innerHTML + , strEmpty = (json === null) || (typeof json === "string" && json.length === 0) + , jsonDat = strEmpty ? null : JSON.parse(json) + ; + if(!strEmpty) { + let res = "" + , $that = $(this) + , $par = $that.parent() + ; + $.each(jsonDat, function() { + let hasOnlyOne = isEmpty(this.surname) || isEmpty(this.firstname) + , pseudonymExists = !isEmpty(this.pseudonym) + , namePart = "" + (hasOnlyOne ? this.surname + this.firstname : this.surname + ", " + this.firstname) + "
" + , pseudoPart = pseudonymExists ? "" + this.pseudonym + "
" : "" + ; + res += namePart + pseudoPart; + }); + $par.append(res); + } + }); + let end = new Date() + , diff = (end - start) + ; + console.log(Math.round(diff) + " ms"); +} + +$(document).ready(function() { + convertJsonData(); +}); +\end{lstlisting} + +Da nun am Client Code ausgeführt wird, nachdem die Daten übertragen wurden, kann nicht mehr alles über das Script +durchgeführt werden. Daher werden nun die Laufzeiten am Server und am Client zusammenaddiert. Im Schnitt benötigt der +Aufruf auf der Serverseite nun 70 ms und am Client sind es circa 13 ms. Dies bedeutet addiert kommt man mit dieser +Lösung auf eine kürzere Laufzeit und weniger Last am Server. + %\mytodos{hier noch darauf eingehen, dass die Hauptarbeit nicht beim editieren sondern bei der Anzeige ist} \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} diff --git a/frontbackmatter/thesis/Acronyms.tex b/frontbackmatter/thesis/Acronyms.tex index 91994bc..796ab64 100644 --- a/frontbackmatter/thesis/Acronyms.tex +++ b/frontbackmatter/thesis/Acronyms.tex @@ -12,7 +12,7 @@ \chapter*{Abk\"{u}rzungsverzeichnis} % Insert your acronyms here (Das Kürzel mit der längsten Bezeichnung sollte in den eckigen Klammern eingetragen werden) -\begin{acronym}[API] +\begin{acronym}[HTML] \acro{EJB}{Enterprise Java Beans} \acro{JSF}{Java Server Faces} \acro{ORM}{Object Relational Mapping} @@ -30,6 +30,7 @@ \acro{GB}{Gigabyte} \acro{SQL}{Structured Query Language} \acro{JVM}{Java Virtual Machine} + \acro{JSON}{JavaScript Object Notation} \end{acronym} \cleardoublepage diff --git a/thesis.pdf b/thesis.pdf index 63c7234..322d277 100644 Binary files a/thesis.pdf and b/thesis.pdf differ diff --git a/thesis.tex b/thesis.tex index d0cffc8..9252397 100644 --- a/thesis.tex +++ b/thesis.tex @@ -36,6 +36,7 @@ %lorem ipsum \lstinline|code| lorem ipsum \input{tools/yaml_syntax_highlighting.tex} +\input{tools/javascript_syntax_hightlighting.tex} %************************************************************************* diff --git a/tools/javascript_syntax_hightlighting.tex b/tools/javascript_syntax_hightlighting.tex new file mode 100644 index 0000000..9be035f --- /dev/null +++ b/tools/javascript_syntax_hightlighting.tex @@ -0,0 +1,72 @@ +\lstdefinelanguage[ECMAScript2015]{JavaScript}[]{JavaScript}{ + morekeywords=[1]{await, async, case, catch, class, const, default, do, + enum, export, extends, finally, from, implements, import, instanceof, + let, static, super, switch, throw, try}, + morestring=[b]` % Interpolation strings. +} + +\lstdefinelanguage{JavaScript}{ + morekeywords=[1]{break, continue, delete, else, for, function, if, in, + new, return, this, typeof, var, void, while, with}, + % Literals, primitive types, and reference types. + morekeywords=[2]{false, null, true, boolean, number, undefined, + Array, Boolean, Date, Math, Number, String, Object}, + % Built-ins. + morekeywords=[3]{eval, parseInt, parseFloat, escape, unescape}, + sensitive, + morecomment=[s]{/*}{*/}, + morecomment=[l]//, + morecomment=[s]{/**}{*/}, % JavaDoc style comments + morestring=[b]', + morestring=[b]" +}[keywords, comments, strings] + +\lstalias[]{ES6}[ECMAScript2015]{JavaScript} + +\definecolor{mediumgray}{rgb}{0.3, 0.4, 0.4} +\definecolor{mediumblue}{rgb}{0.0, 0.0, 0.8} +\definecolor{forestgreen}{rgb}{0.13, 0.55, 0.13} +\definecolor{darkviolet}{rgb}{0.58, 0.0, 0.83} +\definecolor{royalblue}{rgb}{0.25, 0.41, 0.88} +\definecolor{crimson}{rgb}{0.86, 0.8, 0.24} + +\lstdefinestyle{JSES6Base}{ + backgroundcolor=\color{white}, + basicstyle=\ttfamily, + breakatwhitespace=false, + breaklines=false, + captionpos=b, + columns=fullflexible, + commentstyle=\color{mediumgray}\upshape, + emph={}, + emphstyle=\color{crimson}, + extendedchars=true, % requires inputenc + fontadjust=true, + frame=single, + identifierstyle=\color{black}, + keepspaces=true, + keywordstyle=\color{mediumblue}, + keywordstyle={[2]\color{darkviolet}}, + keywordstyle={[3]\color{royalblue}}, + numbers=left, + numbersep=5pt, + numberstyle=\tiny\color{black}, + rulecolor=\color{black}, + showlines=true, + showspaces=false, + showstringspaces=false, + showtabs=false, + stringstyle=\color{forestgreen}, + tabsize=2, + title=\lstname, + upquote=true % requires textcomp +} + +\lstdefinestyle{JavaScript}{ + language=JavaScript, + style=JSES6Base +} +\lstdefinestyle{ES6}{ + language=ES6, + style=JSES6Base +} \ No newline at end of file