Daily CheckIn
This commit is contained in:
parent
0e8b521f17
commit
08647e4632
12 changed files with 169 additions and 33 deletions
|
@ -5,23 +5,24 @@
|
|||
%*******************************************************
|
||||
% If problems with the headers: get headings in appendix etc. right
|
||||
%\markboth{\spacedlowsmallcaps{Appendix}}{\spacedlowsmallcaps{Appendix}}
|
||||
\chapter{JSF Performance Measure}
|
||||
\label{ap:jsf_performance_measure}
|
||||
\chapter{JSF Performance Statistics Servlet}
|
||||
\label{ap:jsf_performance_statistics_servlet}
|
||||
|
||||
Für die Protokollierung der Abläufe im \ac{JSF} werden zwei Klassen benötigt. Die Factory \ref{lst:logger_factory},
|
||||
wird die Wrapper"=Klasse in die Bearbeitungsschicht eingeschleust. Diese Wrapper"=Klasse \ref{lst:logger} beinhaltet
|
||||
dann die eigentliche Performance-Messung, inklusive der Ausgabe in die Log"=Datei des \textit{Glassfish}"=Servers.
|
||||
Zusätzlich muss in der Konfiguration \textbf{faces-config.xml} noch angepasst werden, wie in
|
||||
\ref{lst:logger_factory_activate}, um die Factory durch das System aufrufen zu lassen.
|
||||
Um die Cache-Informationen über einen \ac{API}"=Aufruf bereitzustellen, wird ein Servlet \ref{lst:servlet} und ein
|
||||
Provider \ref{lst:servlet_provider} benötigt. Für die Aufnahme in der Routing, wird noch ein zusätzlicher Eintrag in
|
||||
der \textit{web.xml} benötigt \ref{lst:servlet_activate}.
|
||||
|
||||
\includecode[java]{chapters/thesis/appendix05_Logger.java}{lst:logger}{Vdi Logger}
|
||||
|
||||
\includecode[java]{chapters/thesis/appendix05_LoggerFactory.java}{lst:logger_factory}{Vdi Logger Factory}
|
||||
\includecode[java]{chapters/thesis/appendix05_servlet.java}{lst:servlet}{Performance Statistics Servlet}
|
||||
\includecode[java]{chapters/thesis/appendix05_provider.java}{lst:servlet_provider}{Performance Statistics Provider}
|
||||
|
||||
\begin{lstlisting}[language=xml,caption={Einbindung Factory},label=lst:logger_factory_activate]
|
||||
<factory>
|
||||
<view-declaration-language-factory>
|
||||
de.wedekind.utils.VdlLoggerFactory
|
||||
</view-declaration-language-factory>
|
||||
</factor>
|
||||
\begin{lstlisting}[language=xml,caption={Einbindung Servlet},label=lst:servlet_activate]
|
||||
<servlet>
|
||||
<servlet-name>PerformanceStatisticServlet</servlet-name>
|
||||
<servlet-class>de.wedekind.servlets.PerfStatServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>PerformanceStatisticServlet</servlet-name>
|
||||
<url-pattern>/api/perfstat</url-pattern>
|
||||
</servlet-mapping>
|
||||
\end{lstlisting}
|
||||
|
|
41
chapters/thesis/appendix05_Provider.java
Normal file
41
chapters/thesis/appendix05_Provider.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
public interface PerfStatistics {
|
||||
String getOpenJPAStatistics();
|
||||
String getEntityClasses();
|
||||
}
|
||||
|
||||
@Stateless
|
||||
public class PerfStatisticsImpl implements PerfStatistics {
|
||||
@Inject
|
||||
private EntityManagerJPAFactory entityManagerFactory;
|
||||
private OpenJPAEntityManagerFactory openJPAEntityManagerFactory;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
openJPAEntityManagerFactory = OpenJPAPersistence.cast(entityManagerFactory.getEntityManager().getEntityManagerFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOpenJPAStatistics() {
|
||||
StoreCache cache = openJPAEntityManagerFactory.getStoreCache();
|
||||
|
||||
CacheStatistics st = cache.getStatistics();
|
||||
return String.format("{ \"ReadCount\": %d, \"HitCount\": %d, \"WriteCount\": %d }", st.getReadCount(), st.getHitCount(), st.getWriteCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEntityClasses() {
|
||||
StringBuilder res = new StringBuilder("{ \"Entities\": [");
|
||||
|
||||
EntityManagerFactory emf = openJPAEntityManagerFactory;
|
||||
EntityManager em = emf.createEntityManager();
|
||||
Cache cache = emf.getCache();
|
||||
for(EntityType<?> entityType : em.getMetamodel().getEntities()) {
|
||||
Class<?> cls = entityType.getBindableJavaType();
|
||||
res.append(String.format("\"%s\", ", cls.getCanonicalName()));
|
||||
}
|
||||
res.append("\"\"], \"Cache\": \"");
|
||||
res.append(cache.toString());
|
||||
res.append("\" }");
|
||||
return res.toString();
|
||||
}
|
||||
}
|
25
chapters/thesis/appendix05_servlet.java
Normal file
25
chapters/thesis/appendix05_servlet.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
public class PerfStatServlet extends HttpServlet {
|
||||
private final static Logger m_Logger = Logger.getLogger(PerfStatServlet.class.toString());
|
||||
|
||||
@Inject
|
||||
private PerfStatistics perfStatistics;
|
||||
|
||||
public PerfStatServlet() {
|
||||
m_Logger.info("PerfStatServlet() Constructor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String openJPAStatistics = perfStatistics.getOpenJPAStatistics();
|
||||
String entityClasses = perfStatistics.getEntityClasses();
|
||||
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.setContentType(MediaType.APPLICATION_JSON);
|
||||
PrintWriter out = resp.getWriter();
|
||||
out.print("{ \"openJPAStatistics\": ");
|
||||
out.print(openJPAStatistics);
|
||||
out.print(", \"entityClasses\": ");
|
||||
out.print(entityClasses);
|
||||
out.print(" }");
|
||||
}
|
||||
}
|
27
chapters/thesis/appendix06.tex
Normal file
27
chapters/thesis/appendix06.tex
Normal file
|
@ -0,0 +1,27 @@
|
|||
% !TeX root = ../../thesis.tex
|
||||
|
||||
%********************************************************************
|
||||
% Appendix
|
||||
%*******************************************************
|
||||
% If problems with the headers: get headings in appendix etc. right
|
||||
%\markboth{\spacedlowsmallcaps{Appendix}}{\spacedlowsmallcaps{Appendix}}
|
||||
\chapter{JSF Performance Measure}
|
||||
\label{ap:jsf_performance_measure}
|
||||
|
||||
Für die Protokollierung der Abläufe im \ac{JSF} werden zwei Klassen benötigt. Die Factory \ref{lst:logger_factory},
|
||||
wird die Wrapper"=Klasse in die Bearbeitungsschicht eingeschleust. Diese Wrapper"=Klasse \ref{lst:logger} beinhaltet
|
||||
dann die eigentliche Performance-Messung, inklusive der Ausgabe in die Log"=Datei des \textit{Glassfish}"=Servers.
|
||||
Zusätzlich muss in der Konfiguration \textbf{faces-config.xml} noch angepasst werden, wie in
|
||||
\ref{lst:logger_factory_activate}, um die Factory durch das System aufrufen zu lassen.
|
||||
|
||||
\includecode[java]{chapters/thesis/appendix06_Logger.java}{lst:logger}{Vdi Logger}
|
||||
|
||||
\includecode[java]{chapters/thesis/appendix06_LoggerFactory.java}{lst:logger_factory}{Vdi Logger Factory}
|
||||
|
||||
\begin{lstlisting}[language=xml,caption={Einbindung Factory},label=lst:logger_factory_activate]
|
||||
<factory>
|
||||
<view-declaration-language-factory>
|
||||
de.wedekind.utils.VdlLoggerFactory
|
||||
</view-declaration-language-factory>
|
||||
</factor>
|
||||
\end{lstlisting}
|
|
@ -14,23 +14,37 @@ auf mögliche Optimierungen untersucht und bewertet.
|
|||
Für die Untersuchung des Systems wird der direkte Zugang zum Server benötigt. Hierbei werden zuerst die im Kapitel
|
||||
\ref{sec:basics:services} beschriebenen Einstellungen überprüft.
|
||||
|
||||
Zuerst wird am PostgreSQL"=Server die Konfiguration der Speicher mit der Vorgabe für Produktivsystem abgeglichen.
|
||||
Zuerst wird am PostgreSQL"=Server die Konfiguration der Speicher mit der Vorgabe für Produktivsysteme abgeglichen.
|
||||
Hierunter fallen die Einstellungen für die \textit{shared\_buffers}, der bei einem Arbeitsspeicher von mehr als 1 GB
|
||||
circa 25\% des Arbeitsspeicher definiert sein soll \cite{PostgresC20.4:2024}.
|
||||
circa 25\% des Arbeitsspeicher besitzen sollte \cite{PostgresC20.4:2024}.
|
||||
|
||||
\mytodos{die anderen Speicher abarbeiten?}
|
||||
Bei der Einstellung \textit{temp\_buffers} geht es um den Zwischenspeicher für jede Verbindung, die bei der Verwendung
|
||||
von temporären Tabellen verwendet wird. Dieser Wert sollte auf dem Standardwert von 8 MB belassen werden. Und nur bei
|
||||
der Verwendung von großen temporären Tabellen verändert werden.
|
||||
|
||||
Der Speicher, der für eine Abfrage verwendet werden darf, wird über die Konfiguration \textit{work\_mem} gesteuert.
|
||||
Wenn der Speicher zu gering wird, werden die Zwischenergebnisse in temporäre Dateien ausgelagert. Der empfohlene Wert
|
||||
berechnet sich aus \textit{shared\_buffers} dividiert durch \textit{max\_connections} \citep{ConfigTo12:online}.
|
||||
Sollte der Berechnung außerhalb der Grenzwerte von 1 MB und 256 MB liegen, ist der jeweilige Grenzwert zu verwenden.
|
||||
Um zu ermitteln, ob die Konfiguration richtig ist, muss im PostgreSQL die Einstellung \textit{log\_temp\_files} auf 0
|
||||
gesetzt werden. Mit dieser kann ermittelt, ob temporäre Dateien verwendet werden und deren Größe. Bei vielen kleineren
|
||||
Dateien sollte der Grenzwert erhöht werden. Bei wenigen großen Dateien ist es ist sinnvoll den Wert so zu belassen.
|
||||
|
||||
Für die Wartungsaufgaben wie VACUUM oder dem erstellen von Indexen wird die Begrenzung über die Einstellung
|
||||
\textit{maintenance\_work\_mem} gesetzt. Dieser Wert sollte 5\% des verfügbaren Arbeitsspeicher entsprechen und größer
|
||||
als \textit{work\_mem} sein.
|
||||
|
||||
Dann wird mit dem Systemtools, wie den Konsolenanwendungen \textit{htop} und \textit{free}, die Auslastung des Servers
|
||||
überprüft. Hierbei ist die CPU-Leistung, der aktuell genutzte Arbeitsspeicher, sowie die Zugriffe auf die Festplatte
|
||||
überprüft. Hierbei ist die CPU"=Leistung, der aktuell genutzte Arbeitsspeicher, sowie die Zugriffe auf die Festplatte
|
||||
die wichtigen Faktoren zur Bewertung.
|
||||
|
||||
Die CPU-Leistung sollte im Schnitt nicht die 70\% überschreiten, für kurze Spitzen wäre dies zulässig. Da sonst der
|
||||
Die CPU"=Leistung sollte im Schnitt nicht die 70\% überschreiten, für kurze Spitzen wäre dies zulässig. Da sonst der
|
||||
Server an seiner Leistungsgrenze arbeitet und dadurch es nicht mehr schafft die gestellten Anfragen schnell genug
|
||||
abzuarbeiten.
|
||||
|
||||
Da unter Linux der Arbeitsspeicher nicht mehr direkt freigegeben wird, ist hier die Page-Datei der wichtigere Indikator.
|
||||
Da unter Linux der Arbeitsspeicher nicht mehr direkt freigegeben wird, ist hier die Page"=Datei der wichtigere Indikator.
|
||||
Wenn dieses in Verwendung ist, dann benötigen die aktuell laufenden Programme mehr Arbeitsspeicher als vorhanden ist,
|
||||
wodurch der aktuell nicht verwendete in die Page-Datei ausgelagert wird. Hierdurch erhöhen sich die Zugriffszeiten auf
|
||||
wodurch der aktuell nicht verwendete in die Page"=Datei ausgelagert wird. Hierdurch erhöhen sich die Zugriffszeiten auf
|
||||
diese Elemente drastisch.
|
||||
|
||||
Die Zugriffsgeschwindigkeit, die Zugriffszeit sowie die Warteschlange an der Festplatte zeigt deren Belastungsgrenze auf.
|
||||
|
@ -58,8 +72,8 @@ abgelaufen ist. Ebenso wird nach Standorten sortiert, um zu prüfen mit welchen
|
|||
\mytodos{Hier noch mehr Infos dazu, für was genau die Editoren diese tun}
|
||||
|
||||
Da die Daten in der 3. Normalform in der Datenbank gespeichert werden, sind einige Relationen für die Abfragen
|
||||
notwendig. Dies wird durch die generische Abfrage in \autoref{lst:documentlist} gezeigt. Zusätzlich wird für jedes
|
||||
dargestellte Dokument eine zusätzliche Abfrage durchgeführt, die in \autoref{lst:documentlist_sub} zeigt, dass auch hier
|
||||
notwendig. Dies wird durch die generische Abfrage in \ref{lst:documentlist} gezeigt. Zusätzlich wird für jedes
|
||||
dargestellte Dokument eine zusätzliche Abfrage durchgeführt, die in \ref{lst:documentlist_sub} zeigt, dass auch hier
|
||||
weitere Relationen notwendig sind.
|
||||
|
||||
\includecode[SQL]{chapters/thesis/chapter03_documentlist.sql}{lst:documentlist}{Generische Abfrage der Dokumentenliste}
|
||||
|
@ -104,7 +118,7 @@ welchen Umfang die Umstellungen eine Veränderung im Verhalten der Webseite bewi
|
|||
|
||||
Bei den \ac{JSF} wird eine Zeitmessung eingefügt. Hierfür wird eine \textit{Factory} eingebaut, die sich in die
|
||||
Verarbeitung der Seiten einhängt, und damit die Zeiten für das Ermitteln der Daten, das Zusammensetzen und das
|
||||
Render der Sicht aufgenommen werden können. Die Zeiten werden in die Log°=Datei des \textit{Glassfish}!=Servers
|
||||
Render der Sicht aufgenommen werden können. Die Zeiten werden in die Log"=Datei des \textit{Glassfish}"=Servers
|
||||
hinterlegt und durch das Skript ausgewertet. Somit ist es einfach aufzuzeigen, an welcher Stelle der größte Teil
|
||||
der Verzögerung auftritt.
|
||||
|
||||
|
|
|
@ -17,6 +17,23 @@ prüfen, die den Cache von OpenJPE auswerten}
|
|||
\section{Überprüfung des PostgreSQL und Servers}
|
||||
\label{sec:performance-checking:postgresql-checking}
|
||||
|
||||
Die einfachste Art die Einstellungen zu prüfen ist, die Abfrage in \ref{lst:postgresql-select-settings} am
|
||||
Datenbankserver auszuführen.
|
||||
|
||||
\begin{lstlisting}[language=SQL,caption={Ermitteln der PostgreSQL Einstellungen},label=lst:postgresql-select-settings]
|
||||
SELECT name AS setting_name
|
||||
, setting AS setting_value
|
||||
, unit AS setting_unit
|
||||
FROM pg_settings
|
||||
WHERE name IN (
|
||||
'shared_buffers'
|
||||
, 'temp_buffers'
|
||||
, 'work_mem'
|
||||
, 'max_connections'
|
||||
, 'maintenance_work_mem'
|
||||
)
|
||||
\end{lstlisting}
|
||||
|
||||
\mytodos{Konfiguration vom Produktionsserver prüfen}
|
||||
|
||||
\section{Einbau und Aktivieren von Performance-Messung}
|
||||
|
@ -61,6 +78,9 @@ log_rotation_size = 100MB
|
|||
wichtigste Einstellung ist \textit{log\_min\_duration\_statement}, diese definiert ab welcher Laufzeit eine Abfrage
|
||||
protokolliert werden soll. Mit dem Wert 0 werden alle Abfragen protokolliert. Alle weitere Einstellungen sind so
|
||||
gesetzt, dass nicht unnötige Abfragen für die spätere Auswertung mit \textit{pgBadger} protokolliert werden.
|
||||
Zusätzlich ist die Einstellung \textit{log\_temp\_files} auf 0 zu setzen. Dadurch werden alle erzeugten temporären
|
||||
Dateien und ihre Größe ebenfalls protokolliert. Diese Dateien entstehen, wenn der temporäre Puffer für die Abfrage
|
||||
nicht ausreicht und die Zwischenergebnisse ausgelagert werden müssen.
|
||||
|
||||
\begin{lstlisting}[language=yaml,caption={PostgreSQL Ausgabekonfiguration},label=lst:postgresql_logconf]
|
||||
log_min_duration_statement = 0
|
||||
|
@ -74,6 +94,6 @@ log_error_verbosity = default
|
|||
log_hostname = on
|
||||
log_lock_waits = on
|
||||
log_statement = 'none'
|
||||
log_temp_files = -1
|
||||
log_temp_files = 0
|
||||
log_timezone = 'Europe/Berlin'
|
||||
\end{lstlisting}
|
||||
|
|
|
@ -257,7 +257,7 @@ abfragt.
|
|||
\label{tbl:measure-cached-queries}
|
||||
\end{table}
|
||||
|
||||
\section{Caching im \ac{JPA}}
|
||||
\section{Caching im JPA}
|
||||
\label{sec:performance-investigation-application:caching-jpa}
|
||||
|
||||
%hier ein test vom acf: \acf{JPA}. aber ich seh ihn nicht
|
||||
|
@ -301,7 +301,7 @@ abfragt.
|
|||
%Wie man an den Daten erkennen kann, wird der Cache vom \ac{JPA} für diese Abfrage nicht verwendet, sonst müssten die
|
||||
%Anzahl der Abfragen an die Datenbank drastisch reduziert werden. Selbst die Laufzeit ändert sich nur marginal.
|
||||
|
||||
\section{Caching in \ac{EJB}}
|
||||
\section{Caching in EJB}
|
||||
\label{sec:performance-investigation-application:caching-ejb}
|
||||
|
||||
Die Cache-Einstellungen des \ac{EJB} sind in der Admin-Oberfläche des Payara-Servers zu erreichen. Hier
|
||||
|
@ -327,7 +327,7 @@ Die Cache-Einstellungen des \ac{EJB} sind in der Admin-Oberfläche des Payara-Se
|
|||
\label{tbl:measure-ejb-cache-active}
|
||||
\end{table}
|
||||
|
||||
\section{Abfragen \ac{JPQL}}
|
||||
\section{Abfragen JPQL}
|
||||
\label{sec:performance-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
|
||||
|
@ -579,7 +579,8 @@ CREATE INDEX idx_searchdocument_startdate
|
|||
|
||||
CREATE INDEX idx_searchdocument_addressees_first_entry
|
||||
ON searchdocument
|
||||
(((addressees->0->>'surname')::text), ((addressees->0->>'firstname')::text));
|
||||
( ((addressees->0->>'surname')::text)
|
||||
, ((addressees->0->>'firstname')::text));
|
||||
|
||||
CREATE INDEX idx_searchdocument_city
|
||||
ON searchdocument (city);
|
||||
|
@ -650,8 +651,6 @@ Nach dem Anpassungen haben sich dann die Werte aus \ref{tbl:measure-materialized
|
|||
\label{tbl:measure-materialized-view-ext}
|
||||
\end{table}
|
||||
|
||||
\mytodos{prüfen ob ms oder msec die richtige SI-Einheit ist}
|
||||
|
||||
Da bei der Materialized View das laden der Daten und das wandeln in die Java"=Objekte getrennt programmiert wurde,
|
||||
können hier eigene Zeitmessungen für die zwei Schritte eingebaut werden. Hierfür wird die Zeit vor dem
|
||||
\textit{map}"=Aufruf und der \textit{map}"=Aufruf gemessen. Für den ersten Aufruf, wurde ein \textit{SearchDocument}
|
||||
|
|
|
@ -54,6 +54,15 @@
|
|||
urldate = {2024-03-27}
|
||||
},
|
||||
|
||||
@online{ConfigTo12:online,
|
||||
author = {},
|
||||
title = {Config - Too small work\_mem · pganalyze},
|
||||
url = {https://pganalyze.com/docs/checks/settings/work_mem},
|
||||
month = {},
|
||||
year = {},
|
||||
urldate = {2024-09-12}
|
||||
},
|
||||
|
||||
@online{AspNetCore:2024:MVC,
|
||||
year = 2024,
|
||||
url = {https://learn.microsoft.com/de-de/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.0},
|
||||
|
|
BIN
thesis.pdf
BIN
thesis.pdf
Binary file not shown.
|
@ -102,7 +102,7 @@
|
|||
\include{chapters/thesis/appendix03}
|
||||
\include{chapters/thesis/appendix04}
|
||||
\include{chapters/thesis/appendix05}
|
||||
%\include{chapters/examples/appendix02}
|
||||
\include{chapters/thesis/appendix06}
|
||||
%*************************************************************************
|
||||
% Other Stuff in the Back
|
||||
%*************************************************************************
|
||||
|
|
Loading…
Reference in a new issue