117
MIN-Fakultät Department Informatik Diplomarbeit Wechselwirkungen zwischen Performance und Architektur Analyse, Optimierung und Evaluation am Beispiel des JCommSy Salim RECHENBERG Februar 2009 [email protected] Studiengang Informatik Matr.-Nr. 5596126 Fachsemester 10 Erstgutachter: Professor Dr. Norbert RITTER Zweitgutachter: Dr. Wolf-Gideon BLEEK

Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

Embed Size (px)

Citation preview

Page 1: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

MIN-FakultätDepartment Informatik

Diplomarbeit

Wechselwirkungen zwischen Performance undArchitektur

–Analyse, Optimierung und Evaluation am

Beispiel des JCommSy

Salim RECHENBERG Februar 2009

[email protected] InformatikMatr.-Nr. 5596126Fachsemester 10

Erstgutachter: Professor Dr. Norbert RITTER

Zweitgutachter: Dr. Wolf-Gideon BLEEK

Page 2: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

More computing sins are committed in the name of efficiency (without necessarilyachieving it) than for any other single reason – including blind stupidity.– William A. Wulf (1972)

Page 3: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

i

Abstract

Software architecture is an important aspect of software development. The architecture describes

the structure of the software and improves the communication between those involved in the pro-

ject. Performance is an important runtime aspect of software upon which the software’s acceptance

and thus its success may depend.

A structured architecture induces additional indirections, e. g. more objects and method calls. If

one subsystem is decoupled from another by a third, such indirections are necessary.

Interdependency between architecture and performance of the web application JCommSy is ana-

lysed. Architectural flaws are identified and the resulting refactorings are described. Performance

is analysed by using a profiler. Performance hotspots are identified and optimisations are perfor-

med. The effects of the refactorings and optimisations on both, performance and architecture, are

discussed.

The performance scale is divided into five categories. Indirections are in category I (about 10

nanoseconds) and do not affect the overall performance if category IV-aspects (milliseconds) are

present. Web applications are highly shaped by I/O-operations (IV). Adding an extra layer has no

impact on the performance. For the JCommSy a performance speed-up of 61 percent is achieved

without harming the architecture. Some optimisations increase the complexity, but there is no need

to avoid using indirections for performance reasons.

Abstract (deutsch)

Software-Architektur ist ein wichtiger Aspekt von Software-Entwicklung. Die Architektur be-

schreibt die Struktur der Software und verbessert die Kommunikation zwischen den Projektbetei-

ligten. Performance ist eine wichtige Laufzeiteigenschaft, die über die Akzeptanz der Software

und damit über den Projekterfolg entscheiden kann.

Saubere Architektur resultiert in zusätzlichen Indirektionen, wie z. B. in zusätzlichen Objekten und

Methodenaufrufen. Sieht die Architektur eine Entkopplung zweier Subsysteme durch ein drittes

vor, sind derartige Indirektionen nötig.

Die Wechselwirkungen zwischen Architektur und Performance werden an der Web-Anwendung

JCommSy analysiert. Architekturverletzungen werden identifiziert und die resultierenden Refac-

torings beschrieben. Die Performance wird mit einem Profiler untersucht. Performance-Hotspots

werden identifiziert und entsprechende Optimierungen durchgeführt. Die Auswirkungen der Re-

factorings und Optimierungen auf Performance und Architektur werden diskutiert.

Es werden fünf Kategorien der Performance-Skala eingeführt. Indirektionen haben Auswirkungen

in Kategorie I (ca. 10 Nanosekunden). Sie haben keine Auswirkungen auf die Gesamtperformance,

wenn Kategorie IV-Aspekte (Millisekunden) ebenfalls vorhanden sind. Web-Anwendungen sind

geprägt durch E/A-Operationen (IV). Eine zusätzliche Schicht hat keine Auswirkungen auf die

Performance. Die Performance des JCommSy kann um 61 Prozent verbessert werden, ohne dass

dabei die Architektur negativ beeinflusst wird. Es gibt Optimierungen, die die Komplexität erhö-

hen, aber Indirektionen sollten nicht aus Gründen der Performance vermieden werden.

Page 4: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

ii

Page 5: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

iii

Danksagung

Zuallererst danke ich meinen Betreuern Professor Dr. Norbert Ritter und Dr. Wolf-Gideon Bleek.

Herrn Ritter danke ich dafür, dass er die Erstbetreuung übernommen hat. Seine Anmerkungen,

seine kritischen Fragen und seine aktive Beteiligung bei meinem Diplomarbeitsvortrag waren von

großem Wert. Vielen Dank.

Obwohl diese Diplomarbeit in eine Zeit des Umbruchs in Wolf-Gideons beruflichem Weg gefallen

ist, hat er mir stets zur Seite gestanden und zahlreiche Stunden seiner Zeit zur Verfügung gestellt.

Er hat es vortrefflich verstanden, mich in den richtigen Momenten anzustoßen, mir die Richtung

zu weisen und mir gleichzeitig maximalen Gestaltungsspielraum zu lassen. Seine fachliche Kom-

petenz und sein persönlicher Einsatz und Zuspruch, waren maßgebend für die Entstehung dieser

Arbeit. Vielen Dank, Wolf-Gideon.

Dipl.-Inform. Uwe Zimmer danke ich für die technische Unterstützung. Er hat mir die nötige

Hard- und Software bereitgestellt und ich konnte mich stets darauf verlassen, dass meinen Bitten

bestmöglich entsprochen wurde. Dies war von großem Wert. Vielen Dank, Uwe.

Ilker Daricili und Sönke Thiesen, meinen Weggefährten und Freunden, danke ich besonders. Wir

haben etliche Stunden gemeinsam in unserem Büro verbracht. Durch eure Anwesenheit konnte ich

innerhalb von Minuten Antworten auf Fragen erhalten und in Diskussionen meine Thesen finden

und festigen. Auch menschlich seid ihr eine große Bereicherung und Stütze für mich. Nicht zuletzt

unsere gemeinsamen Pausen haben für den nötigen Ausgleich gesorgt.

Sönke, ich danke dir für deine schonungslose Kritik und deine Bereitschaft alles zu hinterfragen.

Du hast mir sowohl menschlich, als auch fachlich, stets den richtigen Impuls im richtigen Moment

gegeben.

Ilker, dir danke ich für die zahlreichen inhaltlichen Diskussionen, für deine unermüdliche Bereit-

schaft meine Texte Korrektur zu lesen und sie um unzählige Kommas zu bereichern. Auf dich war

immer Verlass.

Jungs, wir sind ein starkes Team.

Anne, dir danke ich besonders für das Korrekturlesen meiner Arbeit. Du hast dich Wort für Wort

durch meine Texte gekämpft und zahlreiche sprachliche Krücken und unpräzise Formulierungen

korrigiert. Ganz herzlichen Dank.

Zum Schluss danke ich meiner Familie und meinen Freunden. Ihr alle habt mir während des letzten

halben Jahres den nötigen Platz gelassen und ward dennoch für mich da, wenn ich euch brauchte.

Vielen Dank.

Page 6: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

iv

Page 7: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

Inhaltsverzeichnis v

Inhaltsverzeichnis

1 Einleitung 11.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.3 Gliederung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.4 Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 Grundlagen 52.1 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2.1.1 Architekturelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.1.2 Architekturstile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.1.3 Saubere Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.1.4 Gründe für die Relevanz von Architektur . . . . . . . . . . . . . . . . . 8

2.2 Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.2.1 Zeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.2.2 Speicher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.2.3 Nebenläufigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2.4 Gute Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2.5 Optimierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2.6 Benchmarking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.2.7 Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.2.8 Performance-Modell in Java . . . . . . . . . . . . . . . . . . . . . . . . 18

2.3 JCommSy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.3.1 Web-Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.3.2 CommSy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.3.3 Migrationsprojekt JCommSy . . . . . . . . . . . . . . . . . . . . . . . . 21

2.3.4 Performance als Kriterium . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.4 Eingesetzte Technologien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.4.1 JavaBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.4.2 Servlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.4.3 Java Server Pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.4.4 Tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.4.5 Hibernate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

2.4.6 Spring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

3 Verwandte Themen 253.1 Performance-Modelle und Performance Engineering . . . . . . . . . . . . . . . 25

Page 8: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

vi Inhaltsverzeichnis

3.1.1 Architektur- und Performance-Modelle . . . . . . . . . . . . . . . . . . 25

3.1.2 Software architecture-based performance engineering . . . . . . . . . . . 26

3.2 Generische Leistungsbewertung einer Mehrschichtenarchitektur . . . . . . . . . 27

3.3 Performance-Antipattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

4 Architekturanalyse 294.1 Ziel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

4.1.1 Abgrenzung: Architekturbewertung . . . . . . . . . . . . . . . . . . . . 29

4.2 Software-Werkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

4.2.1 Sotograph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

4.2.2 Sotoarc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

4.2.3 Alternativen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

4.3 Vorgehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

4.3.1 Allgemeines zum Vorgehen . . . . . . . . . . . . . . . . . . . . . . . . 33

4.3.2 Vorgehen beim JCommSy . . . . . . . . . . . . . . . . . . . . . . . . . 33

4.4 Architektur des JCommSy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

4.4.1 Architekturmodell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

4.4.2 Verletzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

4.5 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

5 Performance-Analyse 395.1 Ziel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

5.2 Vorgehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

5.2.1 Testumgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

5.2.2 Einflüsse des Tomcat . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

5.2.3 Testszenario . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

5.3 Software-Werkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

5.3.1 JMeter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

5.3.2 JProfiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

5.3.3 Alternativen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

5.4 Betrachtungsebenen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

5.4.1 Performance-Kategorien und -Bausteine . . . . . . . . . . . . . . . . . . 48

5.4.2 Innerhalb einer Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

5.4.3 Zusammenspiel von Klassen . . . . . . . . . . . . . . . . . . . . . . . . 51

5.4.4 Architekturelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

5.5 Performance des JCommSy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

5.5.1 Zeitliche Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

5.5.2 Speicherverbrauch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

5.5.3 Auswirkungen von Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . 56

5.5.4 Bewertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

5.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

Page 9: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

Inhaltsverzeichnis vii

6 Ergebnisse der Refactorings und Optimierungen am JCommSy 596.1 Durchgeführte Refactorings und Optimierungen . . . . . . . . . . . . . . . . . . 59

6.1.1 Deserialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

6.1.2 Fachlogik extrahieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

6.1.3 Spring Dependency Injection . . . . . . . . . . . . . . . . . . . . . . . . 67

6.1.4 FileServiceHibernate erweitern . . . . . . . . . . . . . . . . . . . . . . 70

6.1.5 StringBuilder benutzen . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

6.2 Auswirkungen unterschiedlicher JVM-Modi . . . . . . . . . . . . . . . . . . . . 73

6.3 Auswirkungen auf Performance und Architektur . . . . . . . . . . . . . . . . . . 74

6.3.1 Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

6.3.2 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

6.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

7 Allgemeine Schlussfolgerungen 797.1 Externe Bibliotheken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

7.1.1 Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

7.1.2 Rahmenwerke allgemein . . . . . . . . . . . . . . . . . . . . . . . . . . 80

7.2 Vorgehen beim Optimieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

7.2.1 Optimierungen durch Messungen belegen . . . . . . . . . . . . . . . . . 81

7.2.2 In den hohen Kategorien zuerst optimieren . . . . . . . . . . . . . . . . 81

7.2.3 Flaches Profil anstreben . . . . . . . . . . . . . . . . . . . . . . . . . . 82

7.2.4 Performance ist wichtig . . . . . . . . . . . . . . . . . . . . . . . . . . 82

7.3 Auswirkungen von Performance-Optimierungen auf die Architektur . . . . . . . 83

7.3.1 Optimierungen erhöhen die Komplexität . . . . . . . . . . . . . . . . . . 83

7.4 Auswirkungen von sauberer Architektur auf die Performance . . . . . . . . . . . 84

7.4.1 Ausbau von Schichtung oder Einführung von Entwurfsmustern . . . . . . 84

7.4.2 Softwaretechnische Prinzipien . . . . . . . . . . . . . . . . . . . . . . . 85

7.4.3 Performance durch Einhaltung der Architektur . . . . . . . . . . . . . . 85

7.5 Datenbanken . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

7.5.1 Zugriffe bündeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

7.5.2 OR-Mapper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

7.5.3 Datenbankschema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

7.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

8 Schlussbemerkungen 898.1 Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

8.2 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

Literaturverzeichnis 93

A Messergebnisse 99

B Testfälle 103

Page 10: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

viii Inhaltsverzeichnis

Page 11: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

Abbildungsverzeichnis ix

Abbildungs- und Tabellenverzeichnis

Abbildungsverzeichnis

2.1 Aufbau der Sun HotSpot JVM [Sun99] . . . . . . . . . . . . . . . . . . . . . . 19

4.1 JCommSy im Sotoarc (Benutzungsoberfläche) . . . . . . . . . . . . . . . . . . . 31

4.2 Architektur des JCommSy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

5.1 Ausschnitt aus der JMeter-Benutzungsoberfläche . . . . . . . . . . . . . . . . . 43

5.2 Benutzungsoberfläche des JProfiler . . . . . . . . . . . . . . . . . . . . . . . . . 45

5.3 Gegenüberstellung von Ausführungszeiten und Einteilung in die Kategorien . . . 50

6.1 Sequenzdiagramm einer Anfrage vor dem Refactoring (Ausschnitt) . . . . . . . . 62

6.2 Sequenzdiagramm einer Anfrage nach dem Refactoring (Ausschnitt) . . . . . . . 63

6.3 Schematischer Ablauf einer Anfrage an das JCommSy . . . . . . . . . . . . . . 64

6.4 Schematischer Ablauf einer Anfrage für eine Bearbeitenseite . . . . . . . . . . . 65

A.1 Durchschnittliche Antwortzeiten des JCommSy ohne Profiler . . . . . . . . . . . 100

A.2 Gegenüberstellung der minimalen Antwortzeiten mit und ohne Ajax . . . . . . . 101

A.3 Gegenüberstellung der durchschnittlichen Antwortzeiten mit und ohne Ajax . . . 101

Tabellenverzeichnis

5.1 Laufzeiten der Schichten (Stand: 14. Oktober 2008) . . . . . . . . . . . . . . . 54

5.2 Speicherallokationen pro Schichten (Stand: 14. Oktober 2008) . . . . . . . . . . 55

6.1 Vergleich der Ausführungszeiten der Schichten (Stand: 19. Dezember 2008) . . . 75

A.1 Vergleich der unterschiedlichen JVM Modi (Stand: 2. Dezember 2008) . . . . . 99

Page 12: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

x Tabellenverzeichnis

Page 13: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

1

Kapitel 1

Einleitung

Performance ist eine Eigenschaft von Software, mit der jeder Computer-Benutzer konfrontiert ist.

Normalerweise nimmt er sie erst dann wahr, wenn sie den Ansprüchen nicht mehr genügt. Im Ge-

gensatz dazu wird die Architektur einer Software vom Benutzer gar nicht direkt wahrgenommen.

Entwickler hingegen, beschäftigen sich meist explizit mit Architektur. Während Architekturbe-

trachtungen regelmäßig zum Entwicklungsprozess dazugehören, wird der Fokus selten systema-

tisch auf Performance gerichtet. Aufgrund der täglichen Erfahrung mit Software, versuchen Ent-

wickler ständig im Kleinen und bereits während des Programmierens zu optimieren. Solche Opti-

mierungen verringern die Qualität des Quelltextes.

Es ist viel Halbwissen über Performance im Umlauf, was zusammen mit den eigenen Erfahrungen

über langsame Software dazu führt, dass bereits während der Entwicklung und ohne Messungen

optimiert wird. In diesem scheinbaren Spannungsfeld zwischen Architektur und Performance be-

wegt sich diese Arbeit.

1.1 Motivation

Es ist allgemein bekannt, dass Architektur ein wichtiger Aspekt von Software ist, indem sie z. B.

das Systemverständnis unterstützt. Des Weiteren bleibt Software durch eine saubere Architektur

wartbarer, erweiterbarer und wiederverwendbarer.

Unabhängig von expliziten Anforderungen des Kunden, ist jedem Entwickler durch seine eigenen

Erfahrungen bewusst, dass Performance eine Eigenschaft von Software ist, die über deren Akzep-

tanz entscheiden kann.

In dieser Arbeit werden die beiden Aspekte Architektur und Performance zusammengebracht und

untersucht, welche Auswirkungen sie aufeinander haben. Eine saubere Architektur resultiert in der

Regel in zusätzlichen Indirektionen. Andererseits können Direktzugriffe nötig sein, um die Per-

formance zu verbessern. Eine schlecht entworfene Architektur kann die Performance begrenzen.

Diese scheinbaren Widersprüche sind die Grundlage für die im nächsten Abschnitt vorgestellten

und im Laufe der Arbeit behandelten Fragestellungen.

Die betrachtete Software, das JCommSy, ist eine Web-Anwendung mit einer ausgefeilten Archi-

tektur. Sie ist hinreichend komplex, beinhaltet Datenbankzugriffe und integriert eine Reihe von

Rahmenwerken.

Page 14: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2 Kapitel 1 Einleitung

1.2 Zielsetzung

Im Rahmen dieser Arbeit wird dargestellt, wie man Architektur und Performance einer Software

analysiert. Es wird untersucht, wo innerhalb einer Web-Anwendung die für die Performance aus-

schlaggebenden Bereiche liegen. Dies wird auf Architekturebene geschehen.

Nachdem diese Bereiche identifiziert sind, werden dafür Optimierungen untersucht und durchge-

führt. Dabei wird die Performance der Anwendung verbessert werden. Trotzdem ist die absolute

Performance nicht das Primärziel dieser Arbeit. Vielmehr geht es darum, herauszuarbeiten, wo

und wie optimiert werden kann, bzw. an welchen Stellen Optimierungen keinen Mehrwert brin-

gen. Auch Erkenntnisse bezüglich des Vorgehens beim Optimieren werden Ergebnis der Arbeit

sein.

Neben der Performance wird die Architektur der Anwendung verbessert werden. Sie wird ana-

lysiert, um Bereiche zu identifizieren, die verbessert werden können. Die daraus resultierenden

Refactorings werden umgesetzt und das Vorgehen und die Ergebnisse dargestellt. Neben der Ist-

Architektur der Anwendung wird auch die Soll-Architektur weiter ausgearbeitet und eine aktuelle

Dokumentation selbiger entstehen.

Anhand der Optimierungen und Refactorings werden Zusammenhänge zwischen Performance und

Architektur aufgedeckt. Es wird gezeigt werden, inwieweit die durch eine ausgeprägte Architek-

tur oder den Einsatz von Entwurfsmustern hinzukommenden Indirektionen, Auswirkungen auf die

Performance einer Web-Anwendung haben. Ebenso werden die Auswirkungen von Optimierun-

gen auf die Architektur und die Komplexität der Software untersucht und dargestellt.

1.3 Gliederung

Der Aufbau dieser Arbeit wird im Folgenden dargestellt. Dies erlaubt eine Einordnung der Kapitel

und bietet die Möglichkeit gezielt bestimmte Kapitel herauszugreifen.

In dem Kapitel Grundlagen werden für diese Arbeit wichtige Begriffe zu den Themen Architektur

und Performance definiert und zentrale Technologien eingeführt. Der Untersuchungsgegenstand

JCommSy wird vorgestellt.

Das Kapitel Verwandte Themen gibt eine Übersicht über weitere Arbeiten die sich mit dem Zu-

sammenspiel von Architektur und Performance beschäftigen. Dieses Kapitel ist keine Grundlage

für das Verständnis der nachfolgenden Kapitel.

Auf der Basis des Grundlagen-Kapitels wird im Architekturanalyse-Kapitel die Architektur des

JCommSy analysiert. Die dafür nötigen Werkzeuge werden vorgestellt und die Ergebnisse darge-

stellt.

Im Kapitel Performance-Analyse wird die Performance des JCommSy untersucht. Das Vorgehen

und die dafür nötigen Werkzeuge werden eingeführt und die unterschiedlichen Ebenen, auf denen

Performance betrachtet werden kann, dargelegt. Abschließend werden die Ergebnisse der Analyse

beschrieben. Dieses Kapitel bezieht sich auf den Zustand des JCommSy zu Beginn dieser Arbeit.

Das Kapitel Ergebnisse der Refactorings und Optimierungen am JCommSy beschäftigt sich mit

Page 15: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

1.4 Notation 3

den identifizierten Optimierungen und Refactorings. Sie werden einzeln motiviert, die Durch-

führung beschrieben und die Ergebnisse dargestellt. Abschließend wird das JCommSy nach Ab-

schluss aller Optimierungen mit dem Zustand davor verglichen.

Die Ergebnisse werden in Allgemeine Schlussfolgerungen vom JCommSy abstrahiert. Das Kapitel

beschreibt die gewonnenen Erkenntnisse und bewertet sie.

In Schlussbemerkungen wird eine abschließende Zusammenfassung gegeben. Sie besteht aus ei-

nem Ausblick, der offene Punkte erörtert, und einem Fazit.

Liegt das Interesse insbesondere bei den Ergebnissen die das JCommSy betreffen, dann sind die

Abschnitte 2.3, 4.4 und 5.5 sowie das Kapitel 6 von zentraler Bedeutung. Liegt das Interesse am

JCommSy im Hintergrund, können diese Abschnitte ausgelassen werden und der Schwerpunkt

insbesondere auf das Kapitel 7 gelegt werden.

Innerhalb der Abschnitte und Kapitel wird es Verweise zu weiterführende Informationen geben,

sowohl innerhalb dieser Arbeit, als auch auf externe Quellen. Jedes Kapitel schließt mit einer

Zusammenfassung ab, die die Kernaussagen enthält.

1.4 Notation

Im Rahmen dieser Arbeit wird auf eine explizite Erwähnung der weiblichen Formen verzichtet.

Natürlich sind z. B. mit Entwicklern immer auch Entwicklerinnen gemeint.

Programmiersprachliche Konstrukte, wie beispielsweise Klassen- oder Packagenamen, werden in

dieser Schrift geschrieben.

Page 16: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

4 Kapitel 1 Einleitung

Page 17: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5

Kapitel 2

Grundlagen

In diesem Kapitel werden die für diese Arbeit benötigten, grundlegenden Begriffe eingeführt und

definiert. Zentrale Aspekte sind Software-Architektur und Performance, die ausführlich behandelt

werden. Im Performance Abschnitt wird dabei die Java Virtual Machine unter diesen Aspekten

eingeführt. Der Untersuchungsgegenstand dieser Diplomarbeit, das JCommSy, wird vorgestellt,

sowie der Hintergrund aus dem es entstanden ist beleuchtet. Abgeschlossen wird dieses Kapitel

mit der Einführung einiger Technologien, die im Laufe dieser Arbeit von Bedeutung sind.

2.1 Architektur

Einer der zentralen Begriffe dieser Arbeit ist Software-Architektur. Es gibt unterschiedliche Defi-

nitionen für Software-Architektur. Ich folge der Definition von Reussner und Hasselbring, welche

eine Übersetzung der Definition des ANSI/IEEE Standards [Gro00] ist:

Definition 2.1 (Software-Architektur) „Die Software-Architektur ist die grundlegende Organi-

sation eines Systems, dargestellt durch dessen Komponenten, deren Beziehungen zueinander und

zur Umgebung, sowie die Prinzipien, die den Entwurf und die Evolution des Systems bestimmen.“

[RH06, S. 1]

Ein Kernaspekt von Software-Architektur ist, dass die Struktur oder die Strukturen des Systems

als Ganzes im Fokus sind und nicht Teilaspekte wie z. B. das Zusammenspiel einzelner Klassen.

Dies wird auch in der alternativen Definition von Software-Architektur von Bass, Clements und

Kazman so gesehen [BCK98, S. 23]. Der Begriff Komponente ist explizit weit gefasst und stellt

eine Abstraktion eines Teilaspekts der Software dar. Er ist mit Absicht nicht genauer definiert, weil

er unterschiedliche Formen annehmen kann, z. B. Prozesse, Datenbanken oder Packages [BCK98,

S. 23]. Ebenso variieren die Beziehungen der Komponenten, sie können z. B. die Verkörperung

einer Benutzt-Beziehung sein.

In dieser Arbeit verwende ich statt des etwas sperrigen Begriffs Software-Architektur die verkürz-

te Form Architektur.

Jede Software hat eine Architektur, die jedoch nicht immer bekannt sein muss. Damit eine Ar-

chitektur kommuniziert werden kann, sollte sie nicht nur in den Köpfen einzelner Entwickler

vorliegen, sondern durch eine Architekturbeschreibung explizit dokumentiert werden. Eine Archi-

tekturbeschreibung setzt sich aus einem oder mehreren Modellen zusammen (siehe [RH06, S. 36]

und [Gro00]), welche von der Software abstrahieren und dabei einen oder mehrere Aspekte der

Software verdeutlichen und andere ausblenden.

Page 18: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6 Kapitel 2 Grundlagen

Der ANSI/IEEE Standard [Gro00] definiert den Begriff Sicht folgendermaßen: Eine Sicht ist ei-

ne Menge von Modellen, die ein System zu einem bestimmten Aspekt (der Standard spricht hier

von Standpunkten) beschreiben (siehe auch [RH06, S. 36]). Unterschiedliche Autoren definieren

unterschiedliche Standpunkte, wobei ich in dieser Arbeit der Unterteilung in statischer Stand-

punkt, dynamischer Standpunkt und Verteilungs-Standpunkt folgen werde, wie sie von Reussner

und Hasselbring vorgenommen wird [RH06, S. 38]. Vom dynamischen Standpunkt aus wird das

Laufzeitverhalten, wie z. B. die benötigte Ausführungszeit, in den Fokus gerückt. Betrachtet man

eine Architektur von dem Verteilungs-Standpunkt aus, dann ist z. B. von Interesse, welche Pro-

zesse auf welchen Rechnern ausgeführt werden und wie diese Rechner miteinander verbunden

sind. Vom statischen Standpunkt aus erkennt man die Zerlegung des Systems in Komponenten

(Architekturelemente) und deren Abhängigkeiten untereinander.

2.1.1 Architekturelemente

Betrachtet man eine Architektur aus einer statischen Sicht, spricht man anstelle von Komponen-

te, im Sinne der Definition 2.1, von Architekturelement. In der dynamischen und verteilten Sicht

bleibt weiterhin der Begriff Komponente in Verwendung und beschreibt dort ein ausführbares Ar-

tefakt (siehe [Lil08, S. 23]).

In objektorientierten Programmiersprachen entsprechen die Architekturelemente Klassen oder

Subsystemen. Nicht objektorientierte Sprachen werden in dieser Arbeit nicht betrachtet. Neben

diesen zwei Arten von Architekturelementen gibt es drei Arten von Beziehungen: Enthaltensein-,

Benutzt- und Vererbungs-Beziehung. Auf Klassenebene entsprechen die Beziehungen den aus der

Objektorientierung bekannten Beziehungen. Eine Klasse benutzt z. B. eine andere, wenn sie eine

Methode an einem Objekt dieser Klasse aufruft.

Auf der Subsystemebene wird die Enthaltensein-Beziehung wie folgt definiert: Ein Subsystem

kann in einem Subsystem enthalten sein und eine Klasse kann in einem Subsystem enthalten sein.

An dieser Stelle unterscheiden sich Subsysteme von den in Java zur Verfügung stehenden Pack-

ages. Packages können zwar Klassen, jedoch keine anderen Packages enthalten. Die in der realen

Nutzung häufig anzutreffenden hierarchischen Namensräume legen zwar nahe, dass ein Package

in einem anderen enthalten sein kann, jedoch wird dies von der aktuellen Sprachspezifikation nicht

unterstützt. Zukünftig sollen Superpackages die Sprache um ein solches Konstrukt erweitern, mit

dem sich Strukturen oberhalb von Packages aufbauen lassen (siehe [BH09]). Die Benutzt- und

Vererbungsbeziehungen zwischen Subsystemen werden wie folgt definiert: Ein Subsystem benutzt

ein anderes, wenn eine der (indirekt) enthaltenen Klassen eine Klasse aus dem anderen Subsystem

benutzt (und entsprechend für die Vererbungsbeziehung). Diese Definition folgt der Definition von

Lilienthal [Lil08, S. 27 ff.].

Neben Architekturelementen und Beziehungen definiert Lilienthal Schnittstellen als Ausdrucks-

mittel [Lil08, S. 24]. Auf Klassenebene umfasst eine Schnittstelle die Menge aller Methoden, die

an einer Klasse von einer anderen Klasse aufgerufen werden können. Die Schnittstelle eines Sub-

systems wird analog durch alle in ihr enthaltenen Architekturelemente gebildet, die von außerhalb

Page 19: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.1 Architektur 7

des Subsystems sichtbar sind.

2.1.2 Architekturstile

Ein Architekturstil ist eine Lösungsstruktur, die für die Elemente einer Architektur möglichst

durchgängig angewendet werden soll [RH06, S. 87]. Ein Architekturstil enthält Regeln für die

Architekturelemente und deren Beziehungen untereinander [BCK98, S. 25]. Beispielsweise ent-

hält der Stil Schichtenarchitektur die Regel, dass es nur eine Architekturelementart gibt: Schicht.

Für die Beziehungen zwischen Schichten gibt es die Einschränkung, dass eine Schicht über einer

anderen liegt und die Benutzung nur von oben nach unten erlaubt ist.

Ein Architekturstil kann als Abstraktion über eine Menge von Architekturen betrachtet werden,

deren Gemeinsamkeiten in einem oder mehreren Aspekten identifiziert und beschrieben werden

und als Struktur für zukünftige Projekte festgehalten werden (siehe [BCK98, S. 94]). Ein Architek-

turstil verhindert, dass ein beliebiges Design verwendet wird und bringt Struktur in die Software.

Er stellt damit eine „Einschränkung des Designraums“ dar [Lil08, S. 29].

Beispiele für Architekturstile sind Schichtenarchitektur, Subsystemarchitektur oder Referenzar-

chitektur. In einer Schichtenarchitektur gibt es das Architekturelement Subsystem, welches hier

als Schicht bezeichnet wird. Höhere Schichten dürfen untere Schichten benutzen, aber nicht an-

ders herum. Schichten können Schnittstellen aufweisen und dürfen nur über diese benutzt werden.

Auf diese Weise ergibt sich für die entstehende Software eine Struktur, in der u. a. die Klassen

unterer Schichten nicht von denen oberer Schichten abhängen.

Subsystemarchitekturen bestehen aus Subsystemen. Subsysteme stehen in Beziehung zueinander,

wenn Klassen eines Subsystems Klassen des anderen benutzen. Eine Regel, die die erlaubten Be-

ziehungen einschränkt, ist Zyklenfreiheit. Für die Subsysteme kann spezifiziert sein, welche Teile

eines Subsystems zu der öffentlichen Schnittstelle gehören und welche Teile nicht von anderen

Subsystemen benutzt werden dürfen.

Für Referenzarchitekturen sind die Elemente keine Subsysteme, sondern Klassen. Zum Beispiel

legt die Referenzarchitektur Werkzeug-Automat-Material (WAM) fest, dass es u. a. Werkzeuge

und Materialien gibt [Z+98]. Für die Material-Klassen gilt die Einschränkung, dass sie keine

Werkzeug-Klassen benutzen dürfen. Für eine Referenzarchitektur sind die Regeln also auf Klas-

senebene. Es ist möglich, dass eine Software sowohl den Stil Schichtenarchitektur als auch Refe-

renzarchitektur in ihrer Architektur vereinigt. Mit Referenzarchitekturen lassen sich komplexere

und genauere Vorgaben machen, als dies mit einer Schichtenarchitektur möglich ist.

Architekturstile sind insofern ähnlich zu Entwurfsmustern (siehe [GHJV95]), als dass sie eine be-

währte, allgemeine Struktur darstellen, die nach Bedarf eingesetzt werden kann, um das System zu

strukturieren und u. a. leichter kommunizierbar und wartbar zu machen. Aus diesem Grund wird

der Begriff Architekturmuster von einigen Autoren synonym zu Architekturstil verwendet (siehe

z. B. [RH06, S. 342]).

Page 20: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

8 Kapitel 2 Grundlagen

2.1.3 Saubere Architektur

Im Laufe dieser Arbeit, wird die Architektur einer Software analysiert, Veränderungen an dieser

durchgeführt und evaluiert. Eine Architektur an sich ist weder schlecht noch gut. Um die Ar-

chitektur bewerten zu können, müssen zunächst die Begriffe Soll-Architektur und Ist-Architektur

definiert werden. Die Soll-Architektur umfasst die Konzepte und Modelle, die das Entwicklungs-

team der betrachteten Software sich als Zielvorstellung überlegt hat. Als Grundlage dafür wird

häufig ein Architekturstil wie z. B. Schichtenarchitektur verwendet. Nicht immer wird die Soll-

Architektur explizit gemacht und in Dokumenten festgehalten.

Um die Ist-Architektur der Software zu bestimmen, sind folgende Schritte nötig: Aus dem Quell-

text muss ein Modell extrahiert werden. Dieses kann zusammen mit einer Abbildungsvorschrift,

die aus Soll-Architektur und Architekturstil gewonnen wird, zu einer Ist-Architektur angereichert

werden (siehe [Lil08, S. 39]). Beispielsweise muss aus dem Quelltext extrahiert werden, welche

Klassen eines Packages andere Klassen anderer Packages benutzen. Nachdem die einzelnen Pack-

ages mit Hilfe der Soll-Architektur den entsprechenden Architekturelementen zugeordnet worden

sind, erhält man die Beziehungen der Architekturelemente in der Ist-Architektur. Weder das Zu-

ordnen, noch das Extrahieren sind triviale Arbeitsschritte. Das Extrahieren kann z. B. mit Hilfe

von Software-Werkzeugen, wie dem Sotograph (siehe 4.2.1), erfolgen, das Zuordnen muss aber

meistens manuell erfolgen. Es gibt Ansätze, wie von Scharping, die Zuordnung z. B. über Na-

menskonventionen oder Java-Annotationen automatisch zu ermöglichen [Sch08a].

Auf Basis der Ist-Architektur kann die Architektur des Softwaresystems bewertet werden. Da-

für kann sie mit der Soll-Architektur oder dem Architekturstil verglichen werden. Abweichungen

stellen Architekturverletzungen dar. Auf dieser Grundlage, kann dann mit Hilfe eines Qualitätsmo-

dells und einer Gewichtung der unterschiedlichen Qualitätsmerkmale eine Architekturbewertung

durchgeführt werden (siehe Kapitel 4.1.1). Beispiele für Softwarequalitätsmerkmale sind Perfor-

mance und Wartbarkeit.

2.1.4 Gründe für die Relevanz von Architektur

In diesem Abschnitt werden einige Gründe vorgestellt, warum Architektur ein wichtiger Aspekt

von Software ist, insbesondere bei wachsenden Systemen. Es gibt drei Hauptvorteile, die sich aus

der Betrachtung von Architektur ergeben (siehe [BCK98, S. 28] und [CKK02, S. 2]):

1. Kommunikation unter allen Beteiligten

2. Verkörperung früher Design-Entscheidungen

3. Wiederverwendbare Abstraktion über ein System

Die Architektur ermöglicht eine Kommunikation unter den Beteiligten, indem ein gemeinsames

Systemverständnis auf einer konzeptionell hohen Ebene vorliegt. So kann ein Manager aus einer

Architektur ableiten, wie gut sich die Arbeiten parallelisieren lassen, während ein Kunde abschät-

zen kann, wie umfangreich das System wird. Generell kann die Kommunikation auf einer höheren

Page 21: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.2 Performance 9

Ebene erfolgen, indem z. B. über Schichten anstatt von Packages oder gar Klassen gesprochen

wird. Auch ermöglicht das Herausarbeiten der Architektur ein gemeinsames Vokabular, ähnlich

wie es durch Entwurfsmuster möglich ist [GHJV95].

Die Architektur verkörpert die frühen Design-Entscheidungen und bietet eine Grundlage zum

Analysieren und Bewerten. Insbesondere die frühen Design-Entscheidungen haben lange Bestand,

bis hin in die Wartungsphase. Sie müssen nicht nur früh im Prozess getroffen werden, sondern sind

später schwierig zu ändern. Es ist wichtig, diese Entscheidungen möglichst fundiert zu treffen. Die

Architektur ist nicht nur Grundlage für die Struktur des implementierten Systems, sondern auch

für die Struktur des Teams, welches anhand der Architektur in Arbeitsgruppen aufgeteilt wird.

Die Architektur begünstigt, ermöglicht oder verhindert Qualitätseigenschaften des Systems. So ist

z. B. die Veränderbarkeit des Systems von der Kapselung einzelner Subsysteme abhängig. Damit

lassen sich anhand der Architektur Aussagen über die zu erwartenden Qualitätseigenschaften des

Systems machen. Auf dieser Basis können bereits in der Anfangsphase des Projekts sich wider-

sprechende Qualitätsziele diskutiert werden.

Die Architektur erleichtert das Entwickeln von Prototypen, mit denen z. B. die Performance des

Systems frühzeitig abgeschätzt werden kann. Damit sinkt das Risiko, dass das Projekt in späteren

Entwicklungsphasen scheitert.

Die Architektur ist abstrakt genug, um auf andere (ähnliche) Systeme übertragen werden zu kön-

nen und somit wiederverwendet zu werden. Dabei können die Konsequenzen für das entstehende

System mit übernommen werden, also z. B. spezielle Qualitätseigenschaften.

Unter dem Schlagwort „architecture-based development“ versteht man, dass der Fokus weniger

auf dem Programmieren als auf dem Zusammenstellen von Komponenten basiert, welche jeweils

einzeln und unabhängig voneinander entwickelt werden können.

2.2 Performance

In diesem Abschnitt wird der Begriff Performance eingeführt und die Art, wie er in dieser Ar-

beit verwendet wird, abgegrenzt. Es werden die Grundlagen der Optimierung eingeführt. Profiling

wird motiviert und das Vorgehen vorgestellt, wobei auf Besonderheiten bezüglich Java eingegan-

gen wird.

Der englische Begriff Performance lässt sich in vielerlei Hinsicht ins Deutsche übersetzen, z. B.

Auftritt, Leistung, aber auch Effizienz. Unpassend ist die Übersetzung nach „Performanz“, da

dieses Wort im Deutschen nur im Kontext der Sprachwissenschaften existiert [WKKRSS01]. Ich

verwende deswegen in dieser Arbeit das Wort Performance. Fischer und Hofer definieren Perfor-

mance als

„mit irgendwelchen standardisierten oder willkürlichen Massstäben [sic] beurteilte

Leistungsfähigkeit eines Computersystems und/oder seiner Teile“ [FH08, S. 621].

Page 22: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

10 Kapitel 2 Grundlagen

Den Begriff Performance1 definiere ich für diese Arbeit etwas spezieller und auf Softwaresysteme

zugeschnitten wie folgt:

Definition 2.2 (Performance) Die Performance eines Softwaresystems ist dessen messbare Leis-

tungsfähigkeit und beinhaltet dessen Zeit- und Verbrauchsverhalten.

Unter dem Zeitverhalten verstehe ich sowohl die Antwort- und Verarbeitungszeiten als auch den

Durchsatz des Systems. Die Antwortzeit umfasst die Zeit zwischen Eingang eines Ereignisses und

Reaktion des Systems. Am Beispiel einer Desktopanwendung kann dies z. B. die Zeit umfassen,

die zwischen dem Zeitpunkt an dem der Benutzer auf den Laden-Button klickt und dem Zeitpunkt,

an dem das System die ausgewählte Datei geladen und dargestellt hat, vergeht.

Die Verarbeitungszeit umfasst nur die Zeit, die der Computer mit der Berechnung innerhalb der

Anwendung beschäftigt ist. Netzwerkverzögerungen gehören beispielsweise nicht dazu.

Der Durchsatz ist eine Angabe, die Informationen darüber liefert, wieviele Ereignisse ein System

in einem Zeitintervall abarbeiten kann, z. B. wieviele Transaktionen eine Datenbank pro Sekunde

ausführen kann.

Das Verbrauchsverhalten beschreibt die Menge der zur Ausführung benötigten Ressourcen. Der

benötigte Arbeitsspeicher liegt im Fokus des Verbrauchsverhaltens.

Zeit- und Verbrauchsverhalten sind nicht unabhängig voneinander. Werden mehr Ressourcen be-

nötigt, als zur Verfügung stehen, kann, z. B. durch das daraus entstehende Warten auf Ressourcen,

das Zeitverhalten negativ beeinflusst werden. In der Literatur wird Performance zum Teil aus-

schließlich über die Antwortzeiten und den Durchsatz eines Systems definiert [BCK98, S. 79].

Dort wird die Zeit zwischen einem eingehenden Ereignis und der Antwort bzw. die Anzahl der

Ereignisse die in einem Zeitintervall bearbeitet werden können, als die Performance des Systems

definiert.

Nach dem ISO Standard 9126 [ISO01] ist Performance ein Qualitätsmerkmal eines Software-

systems. Die Qualitätsmerkmale einer Software lassen sich in Kategorien einteilen, insbesondere

unterteilen sie sich in solche, die zur Laufzeit am System messbar sind und solche die es nicht

sind (siehe [BCK98, S. 76]). Portierbarkeit und Änderbarkeit sind Beispiele für nicht zur Laufzeit

messbare Eigenschaften. Performance gehört, ebenso wie z. B. Gebrauchstauglichkeit (Usability),

zu den zur Laufzeit messbaren Eigenschaften. Im Vergleich zu der Gebrauchstauglichkeit ist die

Performance jedoch einfach und direkt messbar, z. B. mittels Profiling und Benchmarking (siehe

2.2.7 und 2.2.6).

Die Definition von Performance bezieht den Benutzer des System zunächst nicht mit ein, dies

leistet der Begriff „wahrgenommene Performance“ [WK00]. Die Benutzer nehmen eine Anwen-

dung, die Fortschrittsinformationen anzeigt, als schneller wahr, als eine die das nicht tut [Shi00,

S. 6]. Wenn man es misst, ist das System mit Fortschrittsinformationen höchstens gleichschnell,

in der Regel minimal langsamer. Auch die Varianz in den Antwortzeiten hat einen großen Einfluss

auf die wahrgenommene Performance. Man kann sie verbessern, indem die besonders lange dau-

ernden Anfragen beschleunigt werden, selbst wenn man dabei die durchschnittliche Antwortzeit1In anderen Werken wird anstelle von Performance der Begriff Effizienz verwendet ([RH06, S. 281], [Lil08, S. 71]).

Page 23: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.2 Performance 11

erhöht [Shi00, S. 7].

In den folgenden Abschnitten wird Performance unter den zwei Aspekten Zeit und Speicher be-

trachtet. Es gibt weitere Performance-Größen, auf die hier nicht eingegangen wird [Shi00, S. 16].

2.2.1 Zeit

Um den zeitlichen Aspekt von Performance zu messen, braucht man eigentlich nur eine genaue

Stoppuhr. Man startet den zu messenden Vorgang und misst die Zeit, bis er abgeschlossen ist.

Der Begriff Vorgang ist hier bewusst völlig unspezifisch gehalten (siehe Mikro- und Makro-

Benchmarking), da dieses Verfahren keine Einschränkungen vorgibt. Benchmarks (siehe 2.2.6)

und Profilings (siehe 2.2.7) sind zwei Möglichkeiten diese Art Messungen durchzuführen. Alter-

nativ können die Zeiten von der zu messenden Anwendung selber protokolliert werden, indem

z. B. bei jedem Methodenaufruf die aktuelle Zeit protokolliert wird.

Misst man mit einer Stoppuhr die Zeit, die eine Anwendung für die Abarbeitung einer Methode

braucht, dann misst man deren „wall clock time“. Dabei werden weder andere Prozesse noch an-

dere Threads berücksichtigt, die in der Zwischenzeit auf dem Prozessor ausgeführt wurden [Shi00,

S. 16]. Es wird die real verstrichene Zeit festgehalten. In Anwendungen mit mehreren gleichzeitig

laufenden Threads, kann es dazu kommen, dass die Gesamtzeit die gemessen wurde, länger ist als

die Anwendung real lief.

Im Gegensatz dazu steht die Prozessorzeit-Messung (englisch: CPU Time). Bei dieser Variante

wird nur die Zeit gemessen, die die Methode von dem Prozessor ausgeführt wird. Insbesondere

heißt das, dass wenn ein anderer Prozess oder Thread die Ausführung unterbricht, auch die Mes-

sung unterbrochen wird. Der Nachteil dieser Methode ist, dass die meisten Betriebssysteme die

Prozessorzeit nur in grober Genauigkeit von Millisekunden liefern. Eine feinere Genauigkeit wür-

de einen zu großen Mehraufwand bedeuten [ej-08, S. 35].

Die Zeit könnte auch in Takten oder auszuführenden Befehlen des Prozessors angegeben werden.

Dies ist aber für Hochsprachen wie Java unüblich. Die Softwarewerkzeuge liefern die Zeiten in

der Regel in Mikro- oder Nanosekunden.

2.2.2 Speicher

Zur Ausführung benötigt ein Programm eine gewisse Menge an Arbeitsspeicher. Der benötig-

te Speicher ist nicht direkt für den Benutzer wahrnehmbar, aber er ist dennoch ein wichtiges

Performance-Kriterium. Dies trifft insbesondere auf die beiden Aspekte Gesamtspeicher und Spei-

cherlecks zu. Damit eine Anwendung ohne Geschwindigkeitseinbußen auf einem System laufen

kann, muss der für sie zur Verfügung stehende Arbeitsspeicher mindestens so groß sein, wie der

benötigte Speicher. Dabei kann je nach Anwendungsfall entweder der Durchschnitts- oder der Ma-

ximalspeicherbedarf interessant sein. Laufen auf einem Server viele Anwendungen, ist der Durch-

schnittsspeicherbedarf jeder Anwendung eine wichtige Größe. Unter der Annahme, dass nicht alle

Anwendungen gleichzeitig maximal viel Speicher anfordern, kann der Server mit weniger Spei-

cher auskommen. Obwohl Arbeitsspeicher heute vergleichsweise günstig ist, ist er, gerade unter

Page 24: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

12 Kapitel 2 Grundlagen

dem Aspekt eine Vielzahl von Anwendungen gleichzeitig auf einem System laufen zu lassen, stets

eher zu klein sein.

Der andere wichtige Aspekt, die Speicherlecks (memory leaks), bezeichnet Fehler in Programmen,

die dazu führen, dass angeforderter Speicher nicht wieder freigegeben wird. In Sprachen, in denen

sich der Programmierer selbst um die Speicherverwaltung kümmern muss (z. B. C++), entstehen

Speicherlecks, wenn der Programmierer vergisst, einen mit new angeforderten Speicherbereich mit

delete wieder frei zu geben. Dies resultiert darin, dass die Anwendung mit zunehmender Laufzeit

immer mehr Speicher benötigt. Steht schließlich kein freier Speicher mehr zur Verfügung, kommt

es zu ungewolltem Verhalten, wie einem Programmabbruch.

In Programmiersprachen mit automatischer Speicherverwaltung (z. B. Java), muss ein angeforder-

ter Speicherbereich nicht explizit wieder freigegeben werden. Die Speicherverwaltung sorgt dafür,

dass ein nicht mehr referenziertes Objekt entfernt wird, da es keinen Einfluss auf den weiteren

Programmverlauf mehr hat. Dennoch kann es in solchen Programmiersprachen zu Speicherlecks

kommen, wenn der Programmierer unbeabsichtigt eine Referenz auf ein Objekt behält. Ein sol-

ches Objekt kann, obgleich es eigentlich nicht mehr benötigt wird, nicht vom Garbage Collector

aufgeräumt werden (siehe 2.2.8).

Profiler (siehe 2.2.7) enthalten Werkzeuge, die beim Analysieren von Speicherlecks helfen kön-

nen. Bevor man ein Speicherleck finden kann, muss man zunächst feststellen, dass eines vorhanden

ist. Für Sprachen mit automatischer Speicherverwaltung bietet sich folgendes Vorgehen an. Das

zu untersuchende Programm wird benutzt und dabei beobachtet, ob mit zunehmender Laufzeit der

Speicherverbrauch immer weiter steigt. Dabei muss dafür gesorgt werden, dass das Programm im-

mer wieder in einen Ausgangszustand zurückgesetzt wird. Steigt dennoch der Speicherverbrauch

immer weiter an, ist dies ein Anzeichen für ein Speicherleck.

Der nächste Schritt besteht darin, die Objekte zu identifizieren, die das Leck verursachen. Da-

für wird das Programm gestartet und in seinen Gebrauchszustand gebracht. In diesem Zustand

lässt man den Garbage Collector laufen. Das lässt sich z. B. mittels Profiler komfortabel erledigen.

Anschließend wird die Anzahl an Objekten dokumentiert. Dies ist der Grundzustand in den man

später wieder zurückkehrt.

Auf diesem Zustand aufbauend arbeitet man weiter mit dem Programm und kehrt nach einiger

Zeit in den Grundzustand zurück. Nachdem der Garbage Collector erneut durchgelaufen ist, ver-

gleicht man die nun vorhandene Anzahl an Objekten mit der, die man zuvor gemessen hatte. Wenn

ein Speicherleck vorliegt, dann sollten mehr Objekte vorhanden sein. Wenn dies nicht der Fall ist,

dann benötigt man mehr oder andere Arbeitsschritte zwischen den zwei Messpunkten.

Ausgehend von den neu hinzugekommenen Objekten, müssen jetzt Referenzen zurückverfolgt

werden, um festzustellen, welche sie davon abhalten vom Garbage Collector aufgeräumt zu wer-

den. Profiler bieten hierfür Werkzeuge an, die es dem Programmierer ermöglichen alle Referen-

zen auf ein bestimmtes Objekt anzuzeigen. So kann man die Pfade rückwärts bis zu den Wurzeln

zurückverfolgen. Für eine detaillierte Beschreibung der Möglichkeiten Speicherlecks in Java zu

identifizieren und zu beheben, siehe z. B. Tate [Tat01].

Page 25: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.2 Performance 13

2.2.3 Nebenläufigkeit

Die Performance von Systemen hängt auch von dem Grad an Parallelisierung ab. Durch neben-

läufige Ausführung mehrerer Threads bzw. Prozesse, können Pausen die z. B. durch das Warten

auf externe Speicher entstehen würden, überbrückt werden. Das Verwalten der Threads bzw. Pro-

zesse und deren Synchronisation hat allerdings ebenfalls Auswirkungen auf die Performance. Im

schlimmsten Fall kommt es zu „Deadlocks“, also Situationen in denen mehrere Threads so auf-

einander warten, dass keiner mehr weiterarbeiten kann. Auch Nebenläufigkeitsaspekte lassen sich

mittels Profiler untersuchen, z. B. können die unterschiedlichen Threads und ihre Synchronisati-

onspunkte aufbereitet und dargestellt werden, so dass deutlich wird, welcher Thread aus welchem

Grund aktuell nicht ausgeführt werden kann.

In dieser Arbeit werden Nebenläufigkeitsproblematiken nicht weiter behandelt.

2.2.4 Gute Performance

Mit zunehmendem Verständnis des Begriffs Performance, stellt sich die Frage, wann das Qualitäts-

merkmal Performance erfüllt ist und falls es das nicht ist, wie man die Performance-Eigenschaften

verbessern kann. Performance ist ein wichtiges Kriterium welches Benutzer an Software anlegen

[Shi00, S. 10]. Die Gebrauchstauglichkeit von Software hängt u. a. von der Performance ab (siehe

2.2). In einigen Szenarien ist die Performance ausschlaggebend für die Konkurrenzfähigkeit ei-

ner Software. Performance-Probleme sind eine Ursache für das Scheitern von Softwareprojekten

[Gla97].

Das Verbessern der Performance-Eigenschaften eines Systems ist demnach eine wichtige Tätig-

keit, die jedoch besonders stark strukturiert und eingegrenzt werden muss. Optimieren (siehe 2.2.5)

sollte man stets auf ein Ziel hin. Ein solches Ziel könnte sein, eine bestimmte Anzahl von Bildern

pro Sekunde zu rendern, eine bestimmte durchschnittliche Antwortzeit zu erreichen oder nur eine

bestimmte Menge an Speicher zu benötigen. Hat man kein Ziel formuliert, dann merkt man nicht,

wann man eigentlich aufhören sollte. Generell gilt: Man sollte nicht optimieren, wenn nicht op-

timiert werden muss [Shi00, S. 17]. Optimierung führt zu schlechter lesbarem Quelltext. Selbst

wenn dies in einer gegebenen Situation nicht zutrifft, hätte man in der gleichen Zeit neue Funktio-

nalität entwickeln oder Fehler ausbessern können.

2.2.5 Optimierung

Der Begriff Optimierung bezeichnet den Prozess etwas zu verbessern, also dichter an das Op-

timum heranzubringen. Dementsprechend bezeichnet der Begriff Performance-Optimierung den

Prozess, die Performance zu verbessern. Architektur-Optimierung bezeichnet das Verbessern der

Architektur.

In dieser Arbeit schreibe ich kurz Optimierung, wenn ich Performance-Optimierung meine. Wenn

es um eine andere Art von Optimierung geht, wird dies explizit erwähnt. In anderen Arbeiten wird

statt optimieren auch der Begriff „tunen“ verwendet.

In Bezug auf Software bedeutet optimieren das Transformieren eines Quelltextes in einen neuen

Page 26: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

14 Kapitel 2 Grundlagen

Quelltext. Diese Transformation soll dabei die Korrektheit erhalten und die resultierende Anwen-

dung performanter machen [Bul00, S. xxiii].

Um Struktur in den Prozess der Optimierung zu bringen, wird das Vorgehen mit Hilfe von einer

allgemeinen Strategie und einem Verfahren definiert. Die Strategie sieht vor, dass man immer wie-

der die fünf schwerwiegendsten Flaschenhälse (bottleneck, Hotspots) identifiziert und davon den

korrigiert, der am einfachsten und schnellsten zu korrigieren ist. Danach misst man neu und fängt

von vorne an [Shi00, S. 5].

Es ist wichtig, nicht mit dem schwerwiegendsten Flaschenhals anzufangen, weil sich durch das

Korrigieren des einfachsten schon eine völlig andere Situation ergeben kann. Dies liegt daran,

dass die Flaschenhälse oft nicht unabhängig voneinander sind, sondern Auswirkungen aufeinan-

der haben. Es lohnt sich dementsprechend nicht, viel Zeit in eine Optimierung zu stecken, wenn

diese durch eine andere, schneller durchzuführende Optimierung unnötig gemacht würde.

Typischerweise erhält man durch die ersten Optimierungen Geschwindigkeitsvorteile von einer

Größenordnung, bereits nach einigen Optimierungen nimmt dies stark ab [Shi00, S. 3]. Nach

Bulka gilt auch für Optimierungen die 80-20-Regel, die in diesem Kontext besagt, dass 20 Pro-

zent der Optimierungen 80 Prozent der Performanceverbesserungen bewirken [Bul00, s. xxiv].

Nach Möglichkeit sollte vermieden werden, die anderen 80 Prozent an Optimierungen durchzu-

führen, weil sie den Aufwand und die resultierende Verschlechterung des Quelltextes nicht Wert

sind (s. u.).

Das Verfahren, dem beim Optimieren gefolgt wird, stammt von Shirazi [Shi00, S. 5] und besteht

aus folgenden Schritten:

1. Mittels Profiler die Performance messen (siehe 2.2.7).

2. Flaschenhälse identifizieren und lokalisieren.

3. Eine Hypothese für die Ursache aufstellen.

4. Alle Faktoren in Betracht ziehen, die die Hypothese widerlegen könnten.

5. Einen Test schreiben, der das Problem (Hypothese) isoliert.

6. Die Hypothese überprüfen.

7. Die Anwendung anpassen.

8. Durch Profiling überprüfen, dass die Performance verbessert wurde (und mit Komponen-

tentests sicherstellen, dass sich keine Fehler eingeschlichen haben).

9. Wieder bei Schritt eins anfangen.

Schritt 5 und 7 passieren häufig in Kombination, allerdings kann das den Optimierungsprozess

verlängern, wenn sich erst danach herausstellt, dass die Hypothese falsch war.

Folgende Ressourcen begrenzen typischerweise die Performance: Geschwindigkeit und Verfüg-

barkeit des Prozessors, der Speicher und externe Datenquellen/-senken wie Festplatten oder Netz-

werke. Es sollte stets betrachtet werden, welcher dieser drei Faktoren die Geschwindigkeit in einer

Page 27: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.2 Performance 15

gegebenen Situation begrenzt.

Auf Methodenebene gibt es generell zwei Möglichkeiten bezüglich der Ausführungszeit zu op-

timieren: Entweder oft genutzte Methoden schneller machen oder langsame Methoden weniger

häufig aufrufen. Dies kann z. B. erreicht werden, indem Ergebnisse zwischengespeichert werden.

Die zweite Möglichkeit wird häufig übersehen [WK00].

Eine weitere Möglichkeit die Anwendung zu beschleunigen besteht darin, nicht gebrauchte Funk-

tionalität zu entfernen. Wenn die Anforderungen noch unklar sind, werden Methoden häufig zu

generisch geschrieben. Im Laufe der Entwicklung können solche Methoden dann spezifischer ge-

macht werden. Dies erhöht neben der Performance wahrscheinlich die Les- und Benutzbarkeit,

z. B. weil die Parametertypen spezifischer sind. Optimierter Quelltext ist also weniger generisch

und damit schlechter wiederzuverwenden, weil er mehr an die Anwendungsdomäne angepasst ist

(siehe [Bul00, S. xxiii]).

Das oben beschriebene Verfahren beinhaltet u. a., dass nach jeder Änderung ein Profiling durch-

geführt wird. Dies ist aus zwei Gründen wichtig. Erstens ist nicht klar, ob eine vermeintliche

Verbesserung tatsächlich messbare Vorteile bringt. Zweitens kommt es vor, dass durch die Opti-

mierung einige Funktionen beschleunigt, aber andere verlangsamt werden [Shi00, S. 14]. Es gibt

Situationen in denen das Weglassen von Quelltext in einer Schleife die Performance der Schleife

verschlechtert hat [Ben99]. Dies zeigt, es gibt keine Veränderungen die offensichtlich die Perfor-

mance verbessern. Wenn eine Optimierung sich nicht durch eine Messung bestätigen lässt, dann

sollte sie rückgängig gemacht werden.

Neben dem Profiling müssen auch die Komponententests nach jeder Anpassung ausgeführt wer-

den. Durch die Optimierung schleichen sich Fehler ein [Shi00, S. 15]. Dies liegt daran, dass der

optimierte Quelltext zum Teil schwieriger zu lesen ist [Bul00, S. xxiii]. Deshalb sollte stets ein

Kommentar im Quelltext darauf hinweisen, dass der Quelltext aufgrund von Optimierungen ange-

passt wurde.

Anwendungen wie z. B. Web-Anwendungen, die von mehreren Benutzern gleichzeitig benutzt

werden, sollten zunächst im Ein-Benutzer-Betrieb untersucht werden. Wenn möglich sollten aber

bereits früh in der Entwicklungsphase Tests mit mehreren Benutzern gleichzeitig durchgeführt

werden, da nur so konzeptionelle Probleme entdeckt werden können, die ein Redesign erfordern

(siehe auch 2.2.3).

Bei explizit für Wiederverwendung entwickeltem Quelltext (z. B. Rahmenwerke, Bibliotheken) ist

Optimierung nur mit großer Vorsicht durchzuführen. Es ist dort typischerweise nicht möglich, alle

Anwendungsmöglichkeiten in passenden Tests zu simulieren. Dies macht es schwierig sicherzu-

stellen, dass eine vermeintliche Optimierung die Performance nicht in anderen Anwendungsfällen

verschlechtert [Shi00, S. 358].

2.2.6 Benchmarking

Benchmarking ist neben Profiling eine Möglichkeit die Performance einer Anwendung zu messen.

Beim Benchmarking wird eine quantitative Größe bestimmt, die einen speziellen Aspekt einer An-

Page 28: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

16 Kapitel 2 Grundlagen

wendung kennzeichnet [WK00]. Typischerweise ist diese Größe die Zeit. Dabei kann ein Bench-

mark unterschiedlich große Programmabschnitte messen. Der Bereich reicht von einer einzelnen

Methode (Mikro-Benchmark) bis zu mehreren Use-Cases (Makro-Benchmark). Benchmarking ist

nur dann von Nutzen, wenn man verschiedene Benchmarks miteinander vergleicht. Beispielswei-

se eignet sich Benchmarking, um das Verhalten von zwei unterschiedlichen Sortieralgorithmen in

unterschiedlichen Testfällen gegenüber zu stellen.

Benchmarks können Profiling gut unterstützen. Da sie wiederholbar sein sollen, enthalten sie klar

definierte Programmabläufe. Diese können als wiederholbare Testfälle für das Profiling sinnvoll

sein. Ohne einen solchen Testfall lässt sich eine Änderung, die auf Grund eines Profilings durch-

geführt wurde, schlecht auf ihre Wirksamkeit überprüfen. Es müsste von Hand versucht werden,

den gleichen Programmablauf zu erzeugen. Dies wäre fehleranfällig und zeitaufwendig. Steht mit

einem Benchmark ein definierter Programmablauf zur Verfügung, muss dieser nur erneut angesto-

ßen werden.

Ein dritter Grund, warum Benchmarks sinnvoll sein können, ist, dass sie bereits während der Ent-

wicklungsphase Feedback geben können, wie Änderungen sich auf die Performance auswirken.

Wenn sie während der Entwicklung regelmäßig ausgeführt werden, liefern sie einen ersten Indi-

kator dafür, ob sich die Performance der Anwendung verbessert oder verschlechtert.

Mikro-Benchmarks sind kleine Benchmarks, mit denen kurze Programmabschnitte, wie einzelne

oder wenige Methoden, gemessen werden. Sie können z. B. eingesetzt werden, um zu evaluieren,

welcher Algorithmus in der gegebenen Situation passender ist. Sie stoßen jedoch schnell an ih-

re Grenzen: Wenn z. B. eine moderne HotSpot Java Virtual Machine (JVM) eine Methode erst

bei mehrmaligem Aufruf kompiliert (anstatt sie interpretiert auszuführen), können die Ergebnisse

stark von den im realen Umfeld beobachteten abweichen. Des Weiteren werden die Wechselwir-

kungen mit anderen Teilen des Programms vernachlässigt.

Makro-Benchmarks messen das System auf der gleichen Ebene, wie die Benutzer es verwenden.

Ein oder mehrere Use-Cases können als Grundlage dafür verwendet werden. Es wird versucht mit

Daten zu arbeiten, die den vom Benutzer später eingesetzten Daten entsprechen. Dadurch, dass das

System als Ganzes gestartet und mitgemessen wird, werden Effekte sichtbar, die im Zusammen-

spiel unterschiedlicher Programmteile entstehen. Idealerweise wird ein Makro-Benchmark auf der

Zielumgebung ausgeführt, für die die Anwendung entwickelt wird.

Um die Ergebnisse eines Benchmarks verlässlicher zu machen, werden Benchmarks mehrmals

hintereinander ausgeführt und die entsprechenden Ergebnisse als Ganzes ausgewertet. Damit kön-

nen Ausreißer erkannt und entsprechend behandelt werden. Ausreißer können z. B. durch andere

Prozesse, die im Hintergrund laufen, entstehen. Beim mehrmaligen Ausführen muss beachtet wer-

den, inwieweit durch Caching oder ähnliche Mechanismen die Ausführungszeit späterer Durch-

läufe von den vorherigen abhängt. Insbesondere wenn Java verwendet wird, muss entschieden

werden, ob die gleiche JVM verwendet wird oder nicht. Wenn davon auszugehen ist, dass der

im Benchmark betrachtete Fall in der realen Verwendung nur selten vorkommt, kann es sinnvoll

sein, eine neue JVM zu starten, um zu verhindern, dass mehr als in der realen Anwendungssitua-

Page 29: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.2 Performance 17

tion optimiert wird. Andererseits kann es, gerade für häufig wieder auftretende Anwendungsfälle,

sinnvoll sein, die gleiche JVM zu verwenden, damit die Warm-Up-Phasen weniger ins Gewicht

fallen [WK00]. Die Warm-Up-Phase ist die Zeit, in der die Anwendung noch nicht ihre volle

Leistungsfähigkeit erreicht hat. Dies liegt daran, dass die JVM noch nicht ausreichend Statisti-

ken hat, um zu entscheiden, welche Methoden in nativen Code kompiliert werden sollen (siehe

auch 2.2.8). Beispielsweise kann davon ausgegangen werden, dass ein Web-Server viele Seiten

ausliefert, nachdem er einmal gestartet wurde. Es müssen nicht jedes Mal die benötigten Klassen

geladen werden und die HotSpot JVM hat bereits die häufig aufgerufenen Methoden in nativen

Code kompiliert. Um dem zu entsprechen, sollte dann die JVM nicht neu geladen werden.

2.2.7 Profiling

Im Gegensatz zu Benchmarking wird beim Profiling nicht nach der Gesamtzeit für einen Anwen-

dungsfall gesucht, sondern es wird versucht „performance bottlenecks“ (Flaschenhälse) zu finden.

Diese Hotspot genannten Programmabschnitte, sind dadurch charakterisiert, dass sie einen großen

Teil der Ausführungszeit in Anspruch nehmen.

Profilings werden mit Software-Werkzeugen durchgeführt die als Profiler bezeichnet werden. Mit

diesen kann u. a. festgestellt werden, welche Methoden wie oft aufgerufen wurden, welche Me-

thoden wieviel Prozent der Zeit benötigen und welche Methoden wieviel Speicher anfordern.

Der Profiler liefert die Information, wieviel Zeit eine Methode zur Ausführung braucht. Dabei wird

zwischen der nicht-kumulativen und der kumulativen (geerbten) Zeit unterschieden. Als nicht-

kumulative Zeit, bezeichnet man die Zeit, die das Programm in genau dieser Methode verbringt.

Die Zeit, die es in daraus aufgerufenen Methoden verbringt, wird nicht mit gemessen. Mit Hilfe

der so gewonnenen Zeiten, lassen sich schnell Methoden identifizieren, bei denen sich das Opti-

mieren lohnt.

Wenn es keine Methode mehr gibt, die signifikant mehr Zeit benötigt als die anderen, dann spricht

man von einem flachen Profil [WK00]. Ist die Performance dennoch nicht ausreichend, dann kann

es hilfreich sein, sich die kumulativen Zeiten anzuschauen. Auf diese Weise betrachtet man nicht

nur die Zeit, die das Programm direkt in der Methode ist, sondern auch die Zeit, die es in allen

Methoden verbringt, die aus ihr heraus aufgerufen werden.

Im Folgenden wird Profiling unter Java näher beschrieben. In den Java Versionen vor Java 5 gab

es keine standardisierte Schnittstelle zum Profiling von Java-Anwendungen. Es gab zwar das Java

Virtual Machine Profiler Interface (JVMPI), welches von einigen JVMs implementiert wurde, al-

lerdings konnte sich dieses von Version zu Version ändern. Seit Java 5 gibt es mit dem Java Virtual

Machine Tool Interface (JVMTI) eine standardisierte Schnittstelle, die diesen Missstand behebt

und auf allen JVM Implementierungen zur Verfügung stehen muss. Anhand von diesem Interface

kann ein Profiler sich von der JVM über eine Reihe von Ereignissen informieren lassen. Dazu

gehören das Starten/Beenden der JVM, Ereignisse bezüglich dem Laden von Klassen, bezüglich

dem Lebenszyklus von Threads und bezüglich dem Lebenszyklus von Objekten und dem Garbage

Collector (siehe auch [ej-08, S. 9 ff.]).

Page 30: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

18 Kapitel 2 Grundlagen

Das JVMTI kann auf unterschiedliche Arten benutzt werden, um die Zeiten zu erhalten, die für

die Ausführung einer Methode gebraucht wird. Die Laufzeiten einzelner Methoden können über

Sampling angenähert werden. In kurzen Abständen wird der Aufrufstack des Programms erfragt.

Ist eine Methode bei 100 Aufrufen 10 mal ganz oben auf dem Stack (befindet sich also in der Aus-

führung), dann wird davon ausgegangen, dass sie 10 Prozent der Laufzeit benötigt. Diese Technik

ist nicht sicher oder gar exakt, aber für genügend lange Zeiträume (Sekunden, nicht Millisekun-

den) und entsprechend gewählte Sampling-Raten ist sie brauchbar.

Eine Alternative zum Sampling ist Dynamic Instrumentation [BHM07]. Das Grundprinzip hierbei

ist, dass das Programm vor der Ausführung verändert wird und die Methodenaufrufe so mitproto-

kolliert werden können. In Java ist es möglich, dies dynamisch zu tun, wenn eine Klasse von der

JVM geladen wird. Dafür wird der Bytecode der Klasse dem Profiler zur Verfügung gestellt. Der

Bytecode wird dann vom Profiler so manipuliert, dass z. B. am Anfang und Ende jeder Methode

der Profiler informiert wird. Die manipulierte Klasse wird dann von der JVM geladen und normal

in der Anwendung verwendet. Dies ermöglicht ein genaues Erfassen der Ausführungszeiten und

darüber hinausgehender Informationen. Nachteil dieses Verfahrens ist, dass ein großer Mehrauf-

wand (Overhead) entsteht, wenn in allen Methoden von allen Klassen die Aufrufe protokolliert

werden [Dmi04]. Dynamic Instrumentation begegnet dem Problem, indem nur noch die Klassen,

die der Benutzer wünscht, verändert und damit gemessen werden.

Von Full Instrumentation spricht man, wenn die JVM angewiesen wird, jeden Methodenaufruf

dem Profiler mitzuteilen. Dies produziert einen sehr großen Mehraufwand. Der Vorteil ist, dass

alle Klassen gemessen werden können. Beim Dynamic Instrumentation können nicht alle Klassen

gemessen werden, insbesondere solche nicht, die schon beim Start der JVM geladen werden. Dies

betrifft z. B. solche aus den Packages java.* und sun.* [ej-08, S. 15 f.].

2.2.8 Performance-Modell in Java

Die Entwurfsziele von Java waren u. a. Portabilität und Sicherheit. Der Aspekt Performance wur-

de nie als Hauptziel angesehen. Eine Folge daraus ist, dass es kein richtiges Performance-Modell

für Java gibt. Ein solches wäre nötig, damit verbindliche Aussagen über Performance-Aspekte ge-

macht werden können. Beispielsweise werden keine Aussagen darüber gemacht, ob, und wenn

ja, wie mehrere Threads auf einem Mehrprozessorsystem auf die Prozessoren verteilt werden

[Lea98]. Die Schwierigkeit ein Performance-Modell aufzustellen ist u. a. darin begründet, dass

es viele unterschiedliche Implementierungen der Java Virtual Machine für viele unterschiedliche

Systeme gibt. Dies macht es umso wichtiger, alle Optimierungen auf der Zielplattform mit der

dort verwendeten JVM zu testen. Die Situation wird noch komplizierter, da die JVM eigenständig

und dynamisch optimiert. Dies wird im Folgenden vorgestellt.

In dieser Arbeit beziehe ich mich, falls nicht anders angegeben, auf Java ab Version 5. Seit Java

Version 1.3 setzt Sun Microsystems2 bei den JVM auf die HotSpot-Architektur und nennt die JVM

auch so. Eine HotSpot-JVM besteht aus zwei Komponenten, der Runtime und dem Compiler. Die

2Sun Microsystems hat Java entwickelt und ist einer der führenden JVM Entwickler.

Page 31: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.2 Performance 19

Abbildung 2.1: Aufbau der Sun HotSpot JVM [Sun99]

Runtime enthält einen Java-Bytecode Interpreter und liefert das Speichermanagment und Mecha-

nismen zur Threadsynchronisation. Sie alleine ist eine voll funktionsfähige JVM. Zusätzlich wird

mit dem Compiler eine weitere Komponente zur Verfügung gestellt (siehe Abbildung 2.1). Dieser

Compiler kompiliert zur Laufzeit der Anwendung Java-Bytecode in nativen Maschinencode. Diese

Art von Compiler werden Just-In-Time-Compiler (JIT-Compiler) genannt. Er ist nicht zu verwech-

seln mit javac, der den Java-Quelltext in Java-Bytecode kompiliert. Die Compiler-Komponente

der HotSpot-JVM unterteilt sich wiederum in zwei Varianten. Die Client-Variante enthält einen

simplen Compiler, welcher kaum Optimierungen durchführt. Dieser Compiler braucht weniger

zusätzlichen Speicher und verzögert die Startzeit der Anwendung nicht so stark. Unter Startzeit

ist hier die Zeit gemeint, die der Benutzer warten muss, bis er die Anwendung benutzen kann. Die

Server-Variante enthält einen stark optimierenden Compiler, der die Länge der Warm-Up-Phase

beeinflusst. So dauert es mit der Server-Variante in der Regel deutlich länger, bis die maximale

Performance erreicht ist, diese ist dann aber besser als die der Client-Variante.

Für beide Varianten gilt, dass sie nicht jede Methode kompilieren. Eine Vielzahl an Methoden

werden nur selten aufgerufen. Für diese würde die Gesamtperformance verschlechtert, wenn sie

erst kompiliert und dann ausgeführt würden. Sie werden weiterhin interpretiert. Wenn die Anzahl

der Aufrufe einer Methode einen Grenzwert überschreitet, wird diese Methode kompiliert. Diese

Methoden stellen Hotspots dar (siehe 2.2.7) und sind namensgebend für die JVM. Der Grenz-

wert lässt sich über nicht-standardisierte Parameter der JVM anpassen. Der voreingestellte Wert

ist 1500 für die Client- bzw. 10000 für die Server-Variante [WK00].

Ein wesentlicher Bestandteil der Runtime-Komponente ist der Garbage Collector (GC). Aufgabe

des GC ist es, nicht mehr benötigte Objekte zu finden und zu zerstören, um den belegten Speicher

wieder frei zu geben. Objekte sind dann zu entfernen, wenn sie für die weitere Ausführung des

Programms keine Bedeutung mehr haben. Dies ist aus Sicht des GC dann erreicht, wenn es von

den Wurzelknoten und den lokalen Variablen keine Referenz mehr auf ein Objekt gibt. Auf ein

solches Objekt kann im weiteren Programmverlauf nicht mehr zugegriffen werden. Es erfüllt des-

wegen die Bedingung, dass es keinen Einfluss mehr auf den Programmverlauf hat.

Der GC-Algorithmus hat im Laufe der Entwicklung einige Verbesserungen erfahren. Ein wesent-

liches Konzept ist das Generationen-Konzept. Dem zu Grunde liegt die Beobachtung, dass es viele

kurzlebige Objekte und wenige langlebige Objekte gibt. Die Generation der kurzlebigen Objekte

wird häufiger vom GC durchsucht und erst wenn ein Objekt darin mehrere GC-Zyklen überlebt

Page 32: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

20 Kapitel 2 Grundlagen

hat, wandert es in die Generation der langlebigen Objekte. Verfeinert wird dies durch den so ge-

nannten Train-Algorithmus. Dieser ermöglicht es, die Länge der Pausen, die durch einen GC-Lauf

ausgelöst werden, kurz zu halten und sorgt gleichzeitig dafür, dass zusammenhängende Objekte

im Speicher dicht beieinander liegen. Dies hat insbesondere für Paging und Caching Vorteile. De-

taillierte Informationen zum Garbage Collector und den verwendeten Algorithmen können z. B.

bei Venners [Ven96, Kapitel 9] oder Wilson und Kesselman [WK00] gefunden werden.

2.3 JCommSy

In diesem Abschnitt wird das JCommSy vorgestellt. Dafür wird zunächst eingeführt, was ei-

ne Web-Anwendung ist und anschließend skizziert, was das CommSy ist. Dies führt dann zum

JCommSy.

2.3.1 Web-Anwendung

Das World Wide Web (WWW) ist ein Dienst, der über das Internet angeboten wird. Per Hypertext

wurden anfangs hauptsächlich statische Inhalt miteinander verknüpft und zugänglich gemacht.

Die Struktur des WWW sieht eine Client-Server-Architektur vor: Webbrowser (die Clients) for-

dern Inhalte von Servern an und stellen diese dem Benutzer dar. Mit der Zeit wurden sowohl die

Clientseite als auch die Serverseite weiterentwickelt, so dass heute auf beiden Seiten dynamisch

Inhalte verarbeitet/dargestellt werden können (siehe auch [TSL04, S. 1]). Eine Web-Anwendung

ist definiert als eine Anwendung, die auf einem Server läuft und dort dynamisch Dokumente er-

zeugt und bereitstellt, welche über das Hypertext Transfer Protocol (HTTP) von einem Browser

aus abgerufen und von diesem dargestellt werden. In diese Kategorie fallen beispielsweise Inter-

netshops und das CommSy.

2.3.2 CommSy

Das CommSy3 ist eine an der Universität Hamburg entwickelte Web-Anwendung. Das Projekt

ist 1999 gestartet worden und hat sich seit dem stark weiterentwickelt. Es ist eine „Plattform für

universitäre Lerngemeinschaften“ [CT05, S. 6], in der man zusammen lernen, sowie Projektarbeit

organisieren und unterstützen kann. Insbesondere das projektbasierte Lernen (siehe [JB02]) und

eine gute Benutzbarkeit sind im Fokus der Entwicklung. Über die ursprünglichen Ziele hinausge-

hend, wird das CommSy heute in Schulen und Unternehmen eingesetzt [Sch08b, S. 54].

Das CommSy ist in Räume strukturiert, für die man Mitgliedschaften beantragen kann. Dies er-

möglicht es, geschlossene Lerneinheiten zu erzeugen. Es kann z. B. für jedes Seminar eines Stu-

diengangs einen Raum geben.

In den Räumen werden unterschiedliche Funktionalitäten angeboten. Sie werden Rubriken ge-

nannt. Beispiele für Rubriken sind Ankündigungen, Materialien und Termine. In der Termine-

Rubrik kann z. B. ein Termin mit dem Datum eines Vortrags in einem Seminar angelegt werden.

3http://www.commsy.net/

Page 33: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.3 JCommSy 21

Die Rubriken sind nicht unabhängig voneinander, z. B. kann einem Termin ein Material zugeord-

net werden.

2.3.3 Migrationsprojekt JCommSy

Das CommSy ist in der Skriptsprache PHP geschrieben. Skriptsprachen sind aufgrund ihrer ein-

fachen Erlernbarkeit und guten Unterstützung durch existierende Bibliotheken gerade für Web-

Anwendungen beliebt [Jee05]. Der Nachteil von Skriptsprachen ist besonders in der inneren Qua-

lität der Software zu finden. Im Gegensatz zu äußeren Qualitäten, wie der Performance oder der

Benutzbarkeit, zählen zu den inneren Qualitäten solche, die für den Benutzer nicht wahrnehmbar

sind (siehe auch 2.2). Da die Skriptsprachen keine guten Strukturierungsmöglichkeiten besitzen,

leidet die Lesbarkeit des Quelltextes. Konzepte wie ein Typsystem, das Geheimnisprinzip [Par72]

oder das Vertragsmodell [Mey92] werden nicht unterstützt. Dies macht den Quelltext, gerade bei

wachsenden Systemen, unübersichtlich, fehleranfällig und schwer wartbar [Jee05]. Das trifft umso

mehr zu, wenn die Entwickler noch unerfahren sind, wie z. B. Studierende im Fall des CommSy.

Gerade für Anfänger ist es wichtig, dass es Strukturen und Regeln gibt, die sie anleiten und deren

Verletzungen ggf. automatisiert festgestellt werden können [BPKL06, S. 35].

Um das wachsende CommSy wartbar zu halten, wurde entschieden von PHP auf Java umzustei-

gen, d. h. zu migrieren. Dieses Migrationsprojekt trägt den Namen JCommSy. Ziel ist es, die glei-

che Funktionalität wie das PHP-CommSy anzubieten. Das Vorgehen bei der Migration erfolgt

dabei schrittweise und vertikal (siehe [Jee05]). Es wurde mit einer Rubrik angefangen und die-

se durch alle Schichten hindurch (also Präsentation, Logik, bis zum Datenbankzugriff) auf Java

umgestellt. Sowohl im PHP-CommSy, als auch im JCommSy wurde eine Weiche eingebaut, die

sicherstellt, dass Rubriken, die noch nicht im JCommSy umgesetzt sind, vom PHP-CommSy be-

arbeitet werden.

Im Folgenden bezeichnet PCommSy das in PHP geschriebene CommSy. Der Begriff CommSy

wird nur verwendet, wenn sowohl das in Java als auch das in PHP geschriebene CommSy gemeint

ist.

2.3.4 Performance als Kriterium

Die Entwickler des JCommSy haben, zusammen mit den Entwicklern des PCommSy, eine Reihe

von Kriterien festgelegt, die das JCommSy erfüllen soll. Ein Kriterium ist, dass die Oberfläche,

also das Resultat im Browser des Benutzers, gleich aussehen soll wie die des PCommSy. Des

Weiteren soll die Performance, insbesondere die Zeit, die der Server braucht, um eine Anfrage zu

beantworten, mindestens gleich gut sein, wie die des PCommSy. Um diese Kriterien im Auge zu

behalten, wurden bereits frühzeitig Testfälle definiert, die die Anforderungen regelmäßig überprü-

fen. Diese Tests benutzen das Test-Rahmenwerk HttpUnit4. Mit diesem kann der Web-Server an

seiner Oberfläche getestet werden. Es werden HTTP-Anfragen generiert und entsprechend das in

4siehe http://httpunit.sourceforge.net/

Page 34: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

22 Kapitel 2 Grundlagen

der Antwort erhaltene HTML-Dokument5 ausgewertet.

2.4 Eingesetzte Technologien

In diesem Abschnitt werden relevante Technologien vorgestellt, die im JCommSy eingesetzt und

im Laufe dieser Arbeit verwendet werden. Es wird jeweils eine Einführung mit Verweisen auf

weiterführende Quellen gegeben.

2.4.1 JavaBeans

Eine JavaBean (oder kurz Bean) ist eine in Java geschriebene wiederverwendbare Softwarekompo-

nente. Ursprünglich wurde dieses Komponentenmodell definiert, um Oberflächenerstellungswerk-

zeugen (GUI-Builder) zu ermöglichen, Komponenten wie Textfelder zu verwenden, ohne dass die-

se bereits vorher bekannt sind. JavaBeans müssen übertragbar und damit serialisierbar sein. Damit

z. B. ein GUI-Builder ein Exemplar einer Bean erzeugen kann, schreibt die Spezifikation einen

Standardkonstruktor vor, also einen Konstruktor ohne Parameter. Eine Bean besitzt Eigenschaf-

ten, die über Getter- und Setter-Methoden zugänglich sein müssen. Die Java-Standardbibliothek

enthält eine Reihe von Hilfsklassen, wie z. B. BeanDescriptor, mit dem Informationen über die

Komponente verfügbar gemacht werden können. JavaBeans sind von Sun Microsystems spezifi-

ziert [Ham97].

2.4.2 Servlet

Die Servlet-Programmierschnittstelle (Servlet-API) ist ein wesentlicher Bestandteil von der Ja-

va 2 Plattform Enterprise Edition (J2EE). Sie erlaubt es, auf hohem Abstraktionsniveau Web-

Anwendungen (siehe 2.3.1) zu entwickeln. Dafür werden eine Reihe von Schnittstellen und Klas-

sen angeboten, so dass sich ein Anwendungsentwickler nicht mit dem Parsen und Dekodieren der

HTTP-Anfrage beschäftigen muss. Um ein Servlet zu schreiben, muss der Entwickler im wesent-

lichen nur die Methode doGet implementieren. Diese wird aufgerufen, wenn eine HTTP-GET-

Anfrage eintrifft. Die Methode erhält ein HttpServletRequest- und ein HttpServletResponse-

Objekt als Parameter, welche die Anfrage und die zu erstellende Antwort darstellen. Das Servlet

wird in einen Servlet-Container, wie z. B. dem Apache Tomcat, geladen und von diesem verwaltet.

Dies umfasst das Starten oder Aufrufen des Servlets, wenn eine Anfrage ankommt.

Ein Nachteil, den die ausschließliche Verwendung von Servlets mit sich bringt, ist, dass die

HTML-Tags innerhalb des Servlets in die HTTP-Antwort geschrieben werden müssen. Damit

sind Präsentationsdetails mit der Anwendungslogik vermengt und es ist z. B. nicht einfach mög-

lich, einen Web-Designer die Gestaltung der Oberfläche ändern zu lassen. Dieser müsste dafür das

Servlet bearbeiten, sich also mit der Programmiersprache Java auskennen.

5Hypertext Markup Language (HTML) ist eine Auszeichnungssprache zum Strukturieren von Dokumenten.

Page 35: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

2.4 Eingesetzte Technologien 23

2.4.3 Java Server Pages

Java Server Pages (im Folgenden mit JSP abgekürzt) sind eine Erweiterung der Servlets. Vor dem

ersten Aufruf werden die JSPs vom Servlet-Container in Servlets übersetzt. Sie wurden einge-

führt, um die Darstellungsdetails von der Anwendungslogik trennen zu können und sie z. B. Web-

Designern zugänglich zu machen. JSPs sind in einer HTML ähnlichen Syntax verfasst, erweitern

diese aber um einige Aspekte, so dass in ihnen Java-Quelltext geschrieben werden kann. Die JSPs

sollten als Template-Sprache verstanden werden und ausschließlich für die Darstellung zuständig

sein. Sie sollten z. B. keine Objekte erzeugen und keine Anwendungslogik enthalten, sondern nur

aus übergebenen Objekten die darzustellenden Werte auslesen.

Servlets und JSPs lassen sich sinnvoll gemeinsam verwenden, indem man Servlets für die An-

nahme von Anfragen zuständig sein lässt und aus ihnen heraus die Anwendungslogik aufruft.

Abschließend wird die entsprechende JSP zur Darstellung ausgewählt, welche die Antwortsei-

te generiert. Dies ist eine Implementierung des Model-View-Controller-Musters (MVC) [And03,

S. 52], [ZLMG08, S. 215 ff.]. Im Bereich von Web-Anwendungen wird dieses noch in unterschied-

liche Modelle aufgeteilt. Das Modell 2, welches hier angewendet wird, zeichnet sich dadurch aus,

dass es ein zentrales Einstiegs-Servlet gibt, welches die Veränderung des Modells anstößt und

anschließend an die passende JSP weiterleitet [TSL04, S. 84 ff.].

2.4.4 Tags

Um die JSPs in ihren Möglichkeiten bezüglich der Darstellung nicht einzuschränken, gibt es die

Tag-Bibliotheken. Die JSP Standard Tag Library (JSTL) stellt Kontrollstrukturen wie if oder

forEach in JSP-Syntax für die Verwendung in den JSPs zur Verfügung. Damit kann verhindert

werden, dass in den JSPs für die Darstellungslogik Java-Quelltext geschrieben werden muss. Ne-

ben der vordefinierten JSP Standard Tag Library können eigene Tags definiert werden. Sie können

in JSP-Syntax oder in Java geschrieben werden.

Für weitere Details zu Tags sowie zu Servlets (2.4.2) und JSP(2.4.3) wird auf Kurniawan [Kur02],

Turau [Tur00] sowie Turau, Saleck und Lenz [TSL04] verwiesen.

2.4.5 Hibernate

Moderne Anwendungsentwicklung folgt dem objektorientierten Programmierparadigma [SM02].

Für die Persistenz der Datenbestände werden oft relationale Datenbanken eingesetzt [ZR00]. Um

eine Brücke über den so genannten „impedance mismatch“ zwischen der Objektorientierung und

den relationalen Datenbanken zu schlagen, gibt es objektrelationale Mapper (OR-Mapper). Ein

OR-Mapper leistet die Abbildung von Objekten, wie sie in Java verwendet werden, auf ein rela-

tionales Modell und andersherum. Hibernate6 ist ein solcher OR-Mapper. Darüber hinausgehend,

kann Hibernate den Entwickler davon befreien, Abfragen in der Standard Query Language (SQL)

formulieren zu müssen. Mit der Criteria Query API existiert eine objektorientierte Schnittstelle

um Objekte aus der Datenbank abzufragen (siehe [BHRS07]).6http://www.hibernate.org/

Page 36: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

24 Kapitel 2 Grundlagen

2.4.6 Spring

Das Rahmenwerk Spring verfolgt das Ziel, Java-Entwickler dabei zu unterstützen die Anwendung

gut und einheitlich zu strukturieren und dadurch die Weiterentwicklung zu vereinfachen. Dabei ist

Spring insbesondere eine leichtgewichtige Alternative zu den J2EE-Konzepten [ZLMG08, S. 19].

Es ist modular aufgebaut, so dass nicht alle Komponenten benutzt werden müssen und integriert

existierende Rahmenwerke, wie Hibernate.

Eine konkrete Funktionalität von Spring ist der Dependency Injection (DI) Mechanismus. Dieser

ermöglicht es, dass ein Objekt ein anderes Objekt eines bestimmten Typs erhalten kann, ohne dass

es dieses erzeugen und somit dessen konkrete Klasse kennen muss. In einer Konfigurationsdatei

wird z. B. bekannt gemacht, dass ein Objekt einer Klasse einen Service benötigt. Spring injiziert

diesen Service zur Laufzeit. Dieses folgt dem „Inversion of Control“-Prinzip.

Der DI-Mechanismus wird durch BeanFactorys geleistet. In Spring sind alle verwalteten Klas-

sen Beans, auch wenn sie es im Sinne von Abschnitt 2.4.1 nicht sind. Eine BeanFactory erzeugt

und verwaltet die Objekte und sorgt dafür, dass die korrekten Objekte injiziert werden (siehe

[ZLMG08, S. 35 ff.]).

2.5 Zusammenfassung

In diesem Kapitel wurden die für diese Arbeit nötigen Grundlagen eingeführt. Es wurde definiert,

dass Architektur die grundlegende Organisation eines Systems, bestehend aus Komponenten und

Beziehungen zueinander, darstellt. Architekturen lassen sich zu Architekturstilen zusammenfas-

sen. Architekturstile stellen zusammen mit einer Soll-Architektur den Vergleichspunkt dar, anhand

dessen eine Ist-Architektur bewertet wird und Architekturverletzungen gefunden werden können.

Architektur von Software ist wichtig, weil sie die Kommunikation unterstützt, Designentscheidun-

gen darstellt und auf hoher Ebene Wiederverwendung ermöglicht.

Performance ist der zweite zentrale Begriff dieser Arbeit und wird als messbare Leistungsfähig-

keit eines Softwaresystems definiert. Dabei wird zwischen dem Zeit- und dem Verbrauchsver-

halten unterschieden. Performance ist eine wichtige Qualitätseigenschaft, die über die Akzeptanz

einer Software entscheiden kann. Der Prozess der Verbesserung der Performance wird als Opti-

mierung bezeichnet. Grundlage dafür sind Messungen, die mittels Benchmarking und Profiling

durchgeführt werden. Dabei ist im Bezug auf Java besonders zu beachten, dass Java kein explizi-

tes Performance-Modell besitzt und die JVM mit Hilfe eines eingebauten Compilers optimiert.

Der Untersuchungsgegenstand dieser Arbeit ist das JCommSy, eine Web-Anwendung, die als Mi-

grationsprojekt aus dem CommSy entstanden ist. Das CommSy stellt eine Plattform dar, mit deren

Hilfe projektbasiertes Lernen unterstützt wird.

Servlet, JSP und Tag-Bibliotheken sind die Grundlage für in Java entwickelte Web-Anwendungen.

Sie erlauben eine Entwicklung auf hohem Abstraktionsniveau und ermöglichen eine Trennung von

Darstellung und Anwendungslogik.

Page 37: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

25

Kapitel 3

Verwandte Themen

Performance und Architektur sind zwei wichtige Aspekte von Software (siehe 2.1.4 und 2.2.4). Es

gibt bereits viele Arbeiten, die die beiden Aspekte einzeln betrachten. In diesem Kapitel werden

Arbeiten vorgestellt, die sich mit dem Zusammenhang von Architektur und Performance beschäf-

tigen und deren Kernaussagen dargestellt.

3.1 Performance-Modelle und Performance Engineering

Soll die Performance einer Software untersucht werden, kann es hilfreich sein, von der Software

zu abstrahieren und damit bestimmte Aspekte auszublenden. Geschieht das mit der Absicht, Aus-

sagen über Performance zu machen, dann spricht man von der Erstellung eines Performance-

Modells. Mit dessen Hilfe können Aussagen über die Performance der Software gemacht, Vorher-

sagen abgeleitet oder Kriterien aufgestellt werden. Zur Notation eines Performance-Modells kann

z. B. das „UML Profile for Schedulability, Performance, and Time Specification“ (UML-SPT)

verwendet werden [uml05]. Das UML-SPT-Profil erweitert die bekannten Elemente der Unified

Modeling Language (UML) beispielsweise um Annotationen zur Angabe der benötigten Ausfüh-

rungszeiten.

Im Folgenden werden zunächst Arbeiten zu Performance-Modellen und anschließend darauf auf-

bauende Verfahren vorgestellt.

3.1.1 Architektur- und Performance-Modelle

Marco und Mirandola stellen einen Ansatz vor, um aus Architekturmodellen Performance-Modelle

zu erzeugen [MM06]. Die Autoren stellen fest, dass es besonders wichtig ist, nicht-funktionale

Anforderungen, wie die Performance, bereits auf der Architekturebene zu betrachten. Um die

Performance- und Architekturmodelle gemeinsam verwenden zu können, werden Transformatio-

nen benötigt, die die Modelle ineinander überführen. Verschiedene Performance-Modelle werden

vorgestellt und es wird herausgearbeitet, welche Eigenschaften die unterschiedlichen Transforma-

tionen besitzen. Eine Anforderung an die Transformationen ist die Automatisierbarkeit. Es wird

betrachtet, inwieweit die Transformation von einem Werkzeug automatisiert übernommen werden

kann.

Koziolek, Happe und Becker [KHB06] arbeiten in ihrem Artikel heraus, dass das frühzeitige Er-

kennen von Performance-Eigenschaften einer Architektur es ermöglicht, Designänderungen be-

reits zu Projektbeginn und damit günstiger durchzuführen. Insbesondere bei komponentenbasierter

Software (siehe [And03]), bei der Performance-Daten für die einzelnen Komponenten vorliegen,

Page 38: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

26 Kapitel 3 Verwandte Themen

können auf dieser Grundlage schon frühzeitig Entscheidungen getroffen werden. Die Entwick-

ler einer Komponente kennen den genauen Einsatzkontext in der Regel nicht, deshalb müssen

die Performance-Daten mit dem Einsatzkontext (z. B. Hardwareausstattung, Art der übergebenen

Parameter) parametrisierbar sein. Die Autoren erweitern zu diesem Zweck das UML-SPT-Profil

um eine Möglichkeit, die Performance in Abhängigkeit der Parameter anzugeben. Sie stellen ein

Performance-Vorhersagemodell vor, das explizit die Einflüsse der Parameter und die Benutzung

externer Services berücksichtigt. Dabei arbeiten sie heraus, dass Eigenschaften der Komponenten-

parameter Einfluss haben und diese deshalb spezifizierbar sein müssen. Für eine übergebene Liste

von Elementen ist z. B. deren Länge ein Kriterium, von dem die Performance der Komponente

abhängen kann. Die Autoren zeigen auf, dass parameterabhängige Performance-Spezifikationen

zu besseren Vorhersagen führen. Ihr Modell lässt sich insbesondere bei Anwendungen mit großen

Datenflüssen anwenden.

Reussner und Hasselbring nehmen direkt Bezug auf den Zusammenhang von Architektur und

Performance. Sie stellen fest:

„Zusätzliche Schichten kosten tatsächlich ein paar Maschinenzyklen, aber das ist heu-

te kein Problem“ [RH06, S. 100]

Dies wird damit begründet, dass Performance an anderer Stelle beachtet werden soll, z. B. beim

Datenbankzugriff. Dieser muss so gekapselt sein, dass er später gezielt optimiert werden kann.

Die Architektur sollte flexibel genug sein, dass der Zeitpunkt des Datenbankzugriffs geregelt und

angepasst werden kann.

3.1.2 Software architecture-based performance engineering

„Software performance engineering“ beschreibt die Disziplin, Software so zu entwickeln, dass

sie den Performance-Ansprüchen genügt1. Dabei wird zwischen dem traditionellen und einem

auf Software-Architektur basierenden Ansatz unterschieden. Traditionell wird zuerst die Software

entwickelt und Performance-Fragen ignoriert. Erst während der Integration und der zugehörigen

Testphase wird die Performance betrachtet. Wenn die Performance sich zu diesem Zeitpunkt als

ausreichend herausstellt, dann ist das Vorgehen gerechtfertigt und es gab keine Zusatzkosten.

Wenn die nicht ausreichende Performance, Änderungen nötig macht, dann können diese weit-

reichend und damit teuer sein. Werden die Performance-Probleme erst spät gefunden, kommt es

außerdem zum Problem, den Zeitplan einzuhalten. Ein weiterer Nachteil ist, dass die anderen

nicht-funktionalen Anforderungen eventuell aufgeweicht werden, wenn die Quelltextoptimierun-

gen durchgeführt werden. Beispielsweise kann die Wiederverwendbarkeit unter der Optimierung

leiden (siehe 2.2.5).

Im Gegensatz zu dem traditionellen Ansatz, werden bei dem auf Software-Architektur basieren-

den Ansatz von Anfang an Performance-Aspekte mit behandelt. Bereits bei den ersten Entwurfs-

entscheidungen wird stets die Frage gestellt, ob sie den Performance-Anforderungen genügen.

1Gleichzeitig heißt eine konkrete Methodik auch Software Performance Engineering (SPE).

Page 39: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

3.2 Generische Leistungsbewertung einer Mehrschichtenarchitektur 27

Dafür gibt es Verfahren und Werkzeuge, die den Architekten dabei unterstützen. Der Vorteil die-

ses Vorgehens ist, dass Performance-Probleme bereits früh aufgedeckt werden und entsprechende

Änderungen zu diesem Zeitpunkt noch nicht so aufwendig und teuer sind. Der Nachteil ist, dass

die Entwicklung langsamer ist, da ein weiterer Aspekt behandelt wird. Der Performance-Aspekt

wird auch dann behandelt, wenn er gar kein Problem ist und im traditionellen Ansatz keine Kosten

verursachen würde [Kau03].

Balsamo, Marco, et al. [BMIS04] arbeiten heraus, dass Performance-Analysen noch nicht in den

typischen Softwareentwicklungsprozess integriert sind. Sie stellen Performance-Analyseverfahren

vor und bewerten, wie sie sich in den Entwicklungsprozess integrieren lassen. Ihre Arbeit gibt eine

Übersicht über die vorhandenen Tools und deren Schwächen und Stärken.

Eines der Performance-Analyseverfahren ist Software Performance Engineering (SPE, siehe auch

[RH06, S. 321] und [CKK02, S. 257]). SPE war der erste Ansatz, der Performance-Analyse in

den Entwicklungsprozess integriert. Darauf aufbauend stellen Williams und Smith PASA vor

[WS02]. PASA steht für Performance Assessment of Software Architectures. Dieses szenario-

basierte Vorgehen ermöglicht das frühzeitige Finden von Risiken, wie nicht erfüllte Performance-

Anforderungen. Darüber hinaus gibt es dem Anwender Strategien zur Hand, wie damit umgegan-

gen werden kann.

3.2 Generische Leistungsbewertung einer Mehrschichtenarchitektur

Kune [Kun06] untersucht generische Leistungsbewertung einer Server-basierten Mehrschichten-

architektur auf Basis von der Java Enterprise Edition (J2EE). Der Begriff Leistungsbewertung wird

bei Kune ähnlich, aber nicht gleichbedeutend wie Performance-Analyse, in dieser Arbeit verwen-

det. Der Unterschied liegt darin, das Kune explizit keine Veränderungen am untersuchten System

durchführt. Darüber hinausgehend, wird bei der Untersuchung ein Zugriff auf den Quelltext der

Anwendung explizit ausgeschlossen und dementsprechend generische Konzepte erarbeitet.

Für den generischen Ansatz müssen die betrachteten Systeme eine strikte Implementierung der

J2EE-Architektur sein, also insbesondere aus einem Web-Modul und einem Logik-Modul beste-

hen. Das Web-Modul läuft in Form eines „Web Application Archive“ (WAR) in einem Servlet

Container und enthält keine Fachlogik. Diese läuft in Form von Enterprise JavaBeans (EJB) in

einem EJB-Container. Die Datenbankschicht liegt wiederum darunter und wird per Java Database

Connectivity (JDBC) angesprochen. Alle drei Schichten können zur Laufzeit beobachtet oder sta-

tisch analysiert werden.

Für die Leistungsanalyse werden die drei „Prüfkomponenten“ Filter, Stubs und Driver verwendet.

Die Filter werden einer Schicht vorgelagert und reichern diese um Aufzeichnungsfunktionalitäten

an. Ein Stub wird verwendet, um eine untere Schicht zu simulieren, deren Vermessung zu umge-

hen und Seiteneffekte auszuschließen. Die Driver-Komponenten erzeugen die Anfragen, die die

zu vermessenden Leistungen auslösen. In der vorliegenden Arbeit wird JMeter verwendet um An-

fragen zu erzeugen (siehe 5.3.1). JMeter nimmt die Rolle eines Drivers nach Kunes Terminologie

Page 40: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

28 Kapitel 3 Verwandte Themen

ein. Die drei Prüfkomponenten erlauben es, Performance-Daten nicht nur für die ganze Anwen-

dung, sondern auch für die einzelnen Schichten zu erfassen.

Kune stellt fest, dass es möglich ist, J2EE-basierte Anwendungen auf ihre Leistungsfähigkeit hin

zu untersuchen, ohne den Quelltext zur Verfügung zu haben. Dafür wird eine Striktheit bei der

Trennung der Schichten gefordert, die im JCommSy nicht gegeben ist. Für Kunes Ansatz müssen

die Schichten in Form von einzelnen J2EE-Modulen vorliegen. Der Ansatz bietet keine Mög-

lichkeit, die Performance eines dieser Module genauer zu untersuchen, um Aussagen zu finden,

welche Packages oder Klassen einer Schicht für die Performance der Schicht ausschlaggebend

sind.

3.3 Performance-Antipattern

Antipattern stellen, wie Entwurfs- oder Architekturmuster, Lösungsmöglichkeiten für wiederkeh-

rende Probleme dar. Im Gegensatz zu Entwurfsmustern (siehe [GHJV95]) haben die in den Anti-

pattern beschriebenen Lösungen negative Auswirkungen und sollten nicht umgesetzt werden. Zu

einem Antipattern gehört immer eine alternative Lösung, die beschreibt, wie das Problem besser

gelöst werden kann.

Performance Antipattern sind speziell auf Performance zugeschnittene Antipatterns. Bezüglich

Performance bieten sich Antipattern besonders an, da gute Performance sich durch die Abwesen-

heit von schlechten Lösungen auszeichnet. Smith und Williams haben einen Katalog von Perfor-

mance Antipattern angefangen (siehe [SW00] und [SW02]). Die dort aufgeführten Antipattern

bestehen aus einem Namen, dem Problemfall, in dem sie mit ihren negativen Auswirkungen an-

gewendet werden, und einer Lösung, die beschreibt, wie sie zu vermeiden sind.

Ein Beispiel für ein Antipattern ist „God Class“. Eine God Class entsteht, wenn eine Klasse viel

Funktionalität oder viele Daten enthält. Das Prinzip, Daten und Verhalten zusammen zu halten,

ist verletzt. Übermäßige Kommunikation mit der God Class ist die Folge. Dies ist insbesondere

dann Performance kritisch, wenn Nebenläufigkeit oder entfernte Methodenaufrufe dazu kommen.

Vermieden wird eine God Class, indem die Daten zusammen mit dem zugehörigen Verhalten auf

einzelne Klassen verteilt werden. Eine ausführliche Beschreibung des God Class Antipatterns fin-

det man bei Smith und Williams [SW00].

3.4 Zusammenfassung

In diesem Kapitel wurden verwandte Arbeiten vorgestellt und in Bezug zu dieser Arbeit gestellt.

Mit UML-SPT gibt es eine Sprache, um Performance-Modelle zu erstellen. Software Performance

Engineering ist ein Verfahren, dass die Betrachtung von Performance-Kriterien in den Entwick-

lungsprozess integriert. Performance Antipattern können Entwickler für Performance-Aspekte

sensibilisieren und einen Katalog von zu vermeidenden Lösungsmöglichkeiten bilden.

Page 41: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

29

Kapitel 4

Architekturanalyse

In diesem Kapitel wird die Architektur des JCommSy analysiert. Das Ziel und das Vorgehen der

Analyse wird erklärt und die dafür nötigen Software-Werkzeuge werden vorgestellt. Abschließend

werden die Ergebnisse am Beispiel des JCommSy dargestellt.

4.1 Ziel

Während einer Architekturanalyse wird untersucht, inwieweit die Ist-Architektur einer Software

mit ihrer Soll-Architektur übereinstimmt. Resultate der Analyse sind Änderungen am Software-

system (also an der Ist-Architektur) und/oder an der Soll-Architektur. Eine Architekturanalyse

kann während des gesamten Lebenszykluses eines Projekts stattfinden, sobald ein erster Prototyp

vorhanden ist. Im Idealfall wird während der Entwicklungszeit regelmäßig die Architektur ana-

lysiert, um ein Auseinanderlaufen von Ist- und Soll-Architektur zu verhindern. Die Gründe für

dieses Auseinanderlaufen sind vielfältig. Die fachlichen Anforderungen ändern sich im Laufe der

Entwicklung und nicht immer wird eine nötige Änderung an der Architektur durchgeführt, bzw.

die Auswirkungen auf die Architektur berücksichtigt. Entwickler weichen, gerade unter Zeitdruck

oder wenn die Soll-Architektur nicht ausreichend kommuniziert wird, von den Vorgaben der Soll-

Architektur ab. Details zum Auseinanderlaufen von Soll- und Ist-Architektur findet man in der

Arbeit von Lilienthal [Lil08, S. 41 f.].

4.1.1 Abgrenzung: Architekturbewertung

Der Begriff Architekturanalyse wird teilweise synonym mit dem Begriff Architekturbewertung

verwendet (z. B. von Clements, Kazman und Klein [CKK02] oder Bass, Clements und Kazman

[BCK98]). In diesem Unterabschnitt werden beide Begriffe voneinander abgegrenzt und die Ver-

wendung in dieser Arbeit geklärt.

Im Gegensatz zur eingeführten Architekturanalyse ist das Ziel einer Architekturbewertung eine

(meist frühe) Machbarkeitssicherstellung, indem überprüft wird, ob die Architektur den Anforde-

rungsspezifikationen entspricht. Reussner und Hasselbring definieren Architekturbewertung wie

folgt:

Definition 4.1 (Architekturbewertung) „Die Architekturbewertung umfasst alle Aktivitäten zur

qualitativen oder quantitativen Bestimmung der Qualitätseigenschaften einer Architekturspezifi-

kation. Somit dient die Architekturbewertung der Überprüfung der Qualität der Architekturspezi-

fikation.“ [RH06, S. 282]

Page 42: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

30 Kapitel 4 Architekturanalyse

Im Folgenden wird dementsprechend der Begriff Architekturbewertung verwendet, wenn es dar-

um geht, ob ein System, welches die Architektur umsetzt, die gewünschten Eigenschaften erfüllen

können wird.

Das Bewerten kann mit Hilfe unterschiedlicher Methoden erfolgen. Es werden zwei Kategori-

en unterschieden: qualitative und quantitative Techniken (siehe [RH06, S. 284]). Um z. B. die

Softwarequalität Performance anhand einer Spezifikation zu bewerten, bietet sich die quantitative

Technik Simulation an. Auf diese Weise können, im Gegensatz zur Architekturanalyse, bereits

Aussagen gemacht werden, bevor ein Prototyp existiert. Für weiterführende Informationen über

Architekturbewertungsverfahren, wie Architecture Tradeoff Analysis Method (ATAM), Software

Architecture Analysis Method (SAAM) oder Active Reviews for Intermediate Designs (ARID),

siehe Clements, Kazman und Klein [CKK02]. Detailliertere Informationen bezüglich der Bewer-

tung der Performance erhält man bei Reussner und Hasselbring [RH06, S. 311 ff.].

4.2 Software-Werkzeuge

Bevor im nächsten Abschnitt das Vorgehen bei der Architekturanalyse vorgestellt wird, wird in

diesem Abschnitt ein Überblick über dafür geeignete Software-Werkzeuge gegeben. Dabei werden

insbesondere die während dieser Diplomarbeit eingesetzten Software-Werkzeuge Sotograph und

Sotoarc vorgestellt.

4.2.1 Sotograph

Die Software Sotograph1 erzeugt zu einer bestehenden Software ein Modell, welches in einer

relationalen Datenbank abgelegt wird. Es enthält z. B. Informationen darüber, welches Artefakt

welche anderen Artefakte benutzt. Mit Hilfe von SQL-artigen Anfragen können Eigenschaften

abgefragt und abgeleitet werden. Der Sotograph definiert bereits eine ganze Reihe von Maßen2.

Es lässt sich z. B. abfragen, welche Klassen durch besonders viele oder wenige Methoden auf-

fallen. Eine besonders große Anzahl von Methoden kann ein Anzeichen für eine God Class sein

(siehe 3.3). Hat eine Klasse wenig Methoden, kann dies darauf hindeuten, dass die Methoden in

andere Klassen gehören und die Klasse keine Daseinsberechtigung hat. Neben diesem Maß, gibt

es noch weitere vorgefertigte Maße und die Möglichkeit eigene zu erstellen. Die Maße sind gu-

te Indikatoren für Schwachstellen in der Software-Architektur und können zur Verbesserung der

Qualität der Software beitragen [SM02].

Der Sotograph ermöglicht es, diese Informationen auf höhere Ebenen zu aggregieren. Beispiels-

weise kann aus dem Maß, welche Klassen sich in einem Zyklus gegenseitig benutzen, eine Zy-

klenansicht auf Package-Ebene erzeugt werden.

Des Weiteren kann im Sotograph ein Architekturmodell spezifiziert werden und darüber z. B. fest-

gelegt werden, welche Packages und Klassen welchen Subsystemen angehören. Es kann festge-

1http://www.hello2morrow.com/products/sotograph2In der Literatur wird anstelle des Begriffs Maß auch Metrik verwendet.

Page 43: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

4.2 Software-Werkzeuge 31

Abbildung 4.1: JCommSy im Sotoarc (Benutzungsoberfläche)

legt werden, welche Artefakte oder Subsysteme ein Subsystem benutzen darf. Verletzungen dieser

Vorgaben stellt der Sotograph entsprechend dar.

4.2.2 Sotoarc

Die Software Sotoarc3 baut auf dem in Abschnitt 4.2.1 beschriebenen relationalen Datenbankmo-

dell der Sotograph Software auf. Der Schwerpunkt liegt jedoch nicht darauf, Maße zu ermitteln.

Sotoarc ermöglicht es, die Architektur zu visualisieren, graphisch zu modellieren und zu überprü-

fen.

Abbildung 4.1 zeigt die Benutzungsoberfläche des Sotoarc, in der die Struktur des JCommSy dar-

gestellt wird. Die Linien zwischen den Elementen zeigen Abhängigkeiten auf, wobei die grünen

erlaubt sind und die roten nicht. Auf der linken Seite sind sie von oben nach unten zu lesen, rechts

von unten nach oben. Beispielsweise ist migration abhängig von servlet, aber nicht von tags.

Desweiteren sieht man, dass innerhalb der Service-Schicht api und impl jeweils voneinander ab-

hängig sind, was an dieser Stelle aber erlaubt ist.

3http://www.hello2morrow.com/products/sotoarc

Page 44: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

32 Kapitel 4 Architekturanalyse

Wie schon beim Sotograph werden die Informationen dabei aggregiert. Sie lassen sich bei Bedarf

so weit verfeinern, bis man genau die Quelltextzeile erfährt, die die Abhängigkeit auslöst. Auf die-

se Weise erhält man eine Visualisierung der Beziehungen, sowohl auf abstrakter Ebene, als auch

bei Bedarf detailliert.

Die Möglichkeiten gehen über das reine Betrachten hinaus. Der Sotoarc bietet die Möglichkeit

Subsysteme zu definieren. Innerhalb solcher Subsysteme können wiederum Subsysteme definiert

werden. Packages lassen sich den Subsystemen zuordnen. Mit Hilfe der Subsysteme können die

Architekturvorstellungen abgebildet werden. Subsysteme können z. B. Schichten sein. Ein Sub-

system welches weiter unten liegt, darf dann nicht auf darüberliegende zugreifen. Ordnet man

Packages den Subsystemen zu, dann werden Beziehungen, die die Schichtung verletzen, durch

rote Linien markiert. In Abbildung 4.1 sieht man, dass die Logik-Schicht unerlaubte Zugriffe

auf Klassen aus den Ausstattern und Fragmenten hat. Desweiteren ist das impl-Package aus der

Service-Schicht als private markiert und damit der Zugriff aus dem Migrationspackage verboten.

Damit bietet der Sotoarc die Möglichkeit die Architektur zu analysieren, also insbesondere aufzu-

zeigen, wo die Ist- von der Soll-Architektur abweicht.

Packages können aus einem Subsystem in ein anderes verschoben werden und es gibt unmittelbar

Feedback darüber, wie sich die Benutzt-Beziehungen verändert haben. Beispielsweise wird sofort

dargestellt, ob durch die Verschiebung neue Verletzungen entstehen. Es lassen sich neue Subsyste-

me erstellen und/oder die Eigenschaften über erlaubte Abhängigkeiten verändern. Es ist möglich,

festzulegen, dass zwei Subsysteme eines anderen Subsystems sich gegenseitig nicht benutzen dür-

fen. Insgesamt bietet der Sotoarc damit die Möglichkeit die Architektur zu modellieren.

Der Sotoarc unterstützt den Architekten dabei, die Software anhand der durchgeführten Verschie-

bungen umzustrukturieren. Dies ist nötig, da sich die gemachten Änderungen nur auf das relatio-

nale Modell der Software in der Datenbank auswirken, nicht jedoch auf den eigentlichen Quelltext.

Dafür gibt es einen Refactoring-Report. Dieser enthält jede Veränderung, die am Softwaresystem

durchgeführt werden muss, um die Software in die neue Struktur zu überführen.

4.2.3 Alternativen

Es gibt weitere Werkzeuge, um die Architektur einer Software zu analysieren. Dazu zählen un-

ter anderem JDepend, XRadar, Lattix und SonarJ (siehe [Lil08, S. 64]). Eine Gegenüberstellung

einiger Werkzeuge gibt es von Scharping [Sch05, S. 14 f.]. Im Rahmen dieser Arbeit wird der So-

tograph und insbesondere Sotoarc verwendet und auf die Alternativen nicht weiter eingegangen.

4.3 Vorgehen

Nachdem im letzten Abschnitt die Architekturanalyse-Werkzeuge vorgestellt wurden, wird jetzt

das Vorgehen und deren Benutzung am JCommSy beschrieben. Dabei wird zunächst generell und

anschließend konkret für das JCommSy beschrieben, welche Schritte durchgeführt wurden. Die

Ergebnisse werden im nächsten Abschnitt dargestellt.

Page 45: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

4.3 Vorgehen 33

4.3.1 Allgemeines zum Vorgehen

Lilienthal arbeitet in ihrer Dissertation heraus, dass Architekturanalysen mit Hilfe von Software-

Werkzeugen und Interviews mit den beteiligten Architekten durchgeführt wird [Lil08, S. 61]. Die

hier beschriebene Analyse wurde zusammen mit zwei weiteren Diplomanden durchgeführt (siehe

[Dar09] und [Thi09]). Da alle drei Beteiligten bereits Kenntnisse über die zu betrachtende Soft-

ware haben und selbst an der Entwicklung beteiligt sind und waren, wurde auf die Interviews

weitgehend verzichtet. Die Einarbeitung in die Architekturvorstellungen des Enwicklungsteams

konnte somit entfallen. Aus demselben Grund konnte der Wechsel zwischen Analyse und Umset-

zungen der Umstrukturierungen häufig geschehen und die einzelnen Phasen kurz gehalten werden.

Abgesichert wurden die Überlegungen und Erkenntnisse durch Diskussion und Rücksprache mit

einem der Hauptverantwortlichen und Initiatoren der zu analysierenden Software.

4.3.2 Vorgehen beim JCommSy

Die Architektur des JCommSy war bereits Untersuchungsgegenstand mehrerer Diplom- und Stu-

dienarbeiten (siehe [Sch08b], [Sch05]). Die Arbeit von Schwentner enthielt die aktuellste Archi-

tekturbeschreibung des JCommSy und war Grundlage dieser Analyse. Sie lag jedoch nicht in einer

für den Sotoarc oder Sotograph geeigneten Form vor. Zunächst wurde deshalb die aktuelle Versi-

on des JCommSy im Sotograph eingelesen. Mit dem Sotoarc wurde eine Architekturbeschreibung

modelliert. Diese verfeinerte die Beschreibung von Schwentner und reicherte sie um weitere In-

formationen an. Es wurde vom Großen zum Kleinen vorgegangen, d. h. zuerst wurde nur eine

Einteilung in Schichten vorgenommen, später wurden die einzelnen Schichten genauer model-

liert.

Es stellten sich zwei Aspekte als besonders schwierig heraus. Zum einen die Frage, aus wie vie-

len Schichten das JCommSy besteht und wie diese angeordnet sind. Einhergehend damit wurde

erörtert, ob eine Schichtung genug Informationen transportieren kann oder ob ein anderer Archi-

tekturstil, wie z. B. eine Subsystemarchitektur als Grundlage gewählt werden soll. Zum anderen

wurden die Namensgebungen kontrovers diskutiert, insbesondere als die Schichtung weiter ver-

feinert wurde.

Nachdem sich eine erste Version der Schichtung etabliert hatte, wurde diese im Sotoarc als Modell

hinterlegt. Die einzelnen Packages des JCommSy wurden manuell den Schichten zugeordnet. Der

Sotoarc zeigte eine Reihe von Architekturverletzungen an, die einzeln untersucht wurden. Mit

dem Sotoarc wurde dann evaluiert, ob sich eine Verletzung beseitigen ließe, indem die entspre-

chende Klasse in eine andere Schicht verschoben würde. Wenn dies der Fall war und die Klasse

auch inhaltlich sinnvoll in der anderen Schicht angeordnet war, wurden die nötigen Umbaumaß-

nahmen erfasst. Diese Refactorings wurden umgesetzt und der Quelltext entsprechend angepasst.

Zu diesen Refactorings gehörte auch die Umbenennung von Klassen und die Umgestaltung der

Package-Struktur. Dadurch spiegelt die Package-Struktur die Schichtung fast direkt wider. Ein

Modell für den Sotoarc kann dementsprechend einfach aus der Package-Struktur extrahiert wer-

den, wobei dafür weiterhin manuelle Eingriffe erforderlich sind.

Page 46: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

34 Kapitel 4 Architekturanalyse

Es wurde zwischen der Analyse mittels Sotoarc und dem Umsetzen der ermittelten Refactorings

hin und her gewechselt, bis die Schichtung keine Verletzung mehr enthielt. Für die einzelnen

Schichten wurde die Architektur weiter verfeinert. Innerhalb der einzelnen Schichten wurden Re-

geln definiert welche Subschichten bzw. Subpackages es gibt und welche Regeln für diese gelten.

Um diese Regeln für die Entwickler präsent zu halten, wurde versucht sie z. B. über Namenskon-

ventionen in die Package-Struktur einfließen zu lassen (siehe Service-Schicht in 4.4.1).

4.4 Architektur des JCommSy

Im Rahmen dieser und der Diplomarbeiten von Daricili [Dar09] und Thiesen [Thi09] wurde die

Architektur mit dem Sotoarc analysiert und die Soll-Architektur weiterentwickelt. Um die Ist-

Architektur mit der Soll-Architektur in Einklang zu bringen, wurden die dafür nötigen Umstruktu-

rierungen am System umgesetzt. Die resultierende Architektur wird in den folgenden Abschnitten

vorgestellt.

In den Jahren 2005 und 2006 wurde die Architektur des JCommSy von Lilienthal analysiert [Lil08,

S. 177 ff.].

4.4.1 Architekturmodell

Die Architektur des JCommSy lässt sich, wie in Abbildung 4.2 dargestellt, als Schichtenarchitek-

tur auffassen. Ganz oben liegt die Präsentationsschicht. Diese enthält neben den technologieabhän-

gigen Darstellungskomponenten Servlet, tag und JSP (siehe 2.4.2, 2.4.4 und 2.4.3) die JCommSy

spezifischen Darstellungskomponenten Ausstatter und Fragmente. Die dargestellte Logik-Schicht

ist noch nicht im JCommSy enthalten, soll jedoch später die fachliche Logik enthalten. Diese ist

derzeit noch in den Ausstattern enthalten. Services stellen die fachlichen Objekte aus der Item-

Schicht zur Verfügung und verwalten deren Persistierung in der Datenbank. Dafür wird der OR-

Mapper Hibernate (siehe 2.4.5) eingesetzt. Die unterste Schicht enthält CommSy spezifische Wert-

artige Objekte wie z. B. ItemType oder ItemID.

Das Util-Subsystem wird aus allen Schichten außer Domainvalue benutzt, benutzt selber aber kei-

ne der Schichten und ist deshalb an der Seite angeordnet. Die Schichtung ist nicht strikt, d. h. es

wird nicht nur auf die direkt unter einer Schicht liegende Schicht zugegriffen. Die Beziehungen

sind nicht explizit durch Pfeile dargestellt, da alle erlaubten Benutzt-Beziehungen tatsächlich vor-

handen sind. Die einzige Ausnahme ist, dass die Domainvalue-Schicht nicht auf die Util-Schicht

zugreift.

Die Subsysteme des JCommSy geben die Package-Struktur des JCommSy vor. Sie werden im

Folgenden detaillierter vorgestellt.

• util enthält Hilfsklassen, die sich nicht in eine Schichtung eingliedern lassen, z. B. weil

sie von vielen oder allen Schichten aus benutzt werden. Klassen, die in diesem Package

liegen, dürfen keine Klassen aus anderen JCommSy-Packages benutzen. Ein Beispiel ist die

CommsyException.

Page 47: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

4.4 Architektur des JCommSy 35

domainvalue

item

service

logic

presentation

util

Schichtung des JCommSy Präsentationsschicht (detailliert)

servlet jsp, tag Technologie

outfitter fragment Struktur

Service-Schicht (detailliert)

api Schnittstelle

impl Implementierung

Abbildung 4.2: Architektur des JCommSy

• domainvalue enthält Wert-artige JCommSy spezifische Typen. Es ist eine passive Schicht,

die von den anderen benutzt wird, ohne selber andere zu benutzen. Beispiele für Fachwerte

sind ItemID und FilterPattern.

• item enthält die fachlichen Klassen des JCommSy, welche persistiert werden. Das Package

enthält Klassen wie Group oder User, die die entsprechenden Gegenstände der CommSy-

Welt darstellen.

• services bieten die Möglichkeit, Items zu erhalten, zu speichern, zu erstellen und zu lö-

schen. Sie haben damit eine CRUD-artige Schnittstelle. CRUD stammt aus der Datenbank-

welt und kürzt die grundlegenden Datenbankoperationen „create“, „retrieve“, „update“ und

„delete“ ab. Darüber hinaus sichern sie fachliche Konsistenz zu, sorgen also z. B. dafür, dass

beim Speichern die ItemIDs korrekt gesetzt sind und Informationen darüber, wer das Item

zuletzt verändert hat, gespeichert werden.

Die Services sind von außerhalb über das Package services.api zu benutzen. Auf diese

Weise ist die Verwendung des Hibernate-Rahmenwerks vollständig in der Service-Schicht

gekapselt. Ein Beispiel für ein Element dieser Schicht ist UserService.

• logic soll die fachliche Logik enthalten, die das JCommSy ausmacht. Dieses Package ist

noch leer, entsprechende Funktionalität ist somit fälschlicherweise in anderen Subsystemen.

Im Laufe dieser Arbeit wird die Fachlogik in diese Schicht extrahiert werden.

• presentation.fragments enthält Fragmente. Diese Bean-artigen Klassen (siehe 2.4.1) sind

Datenbehälter für die Präsentationsschicht. Sie werden von den Ausstattern mit den darzu-

stellenden Inhalten befüllt. Die JSPs benutzen sie, um die anzuzeigenden Daten zu erhalten.

Wie auch die JSPs, werden die Fragmente in einer Baumstruktur zusammengestellt. Ein

Fragment entspricht einer JSP und enthält die dafür nötigen Daten. Ein Beispiel ist die

Page 48: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

36 Kapitel 4 Architekturanalyse

Klasse AnnouncementDetail, welche Informationen über eine Ankündigung enthält, wie sie

in der Detailansicht dargestellt werden.

• presentation.outfitter enthält die Ausstatter. Diese sind ebenfalls in einer Baumstruktur

zusammengesteckt und befüllen die zugehörigen Fragmente. Durch die Einführung einer

JavaBean, der ParamBean, ist dieses Subsystem bereits von dem Servlet-Rahmenwerk ent-

koppelt (siehe [Sch08b]). Der GroupDetailOutfitter liest beispielsweise aus dem entspre-

chenden Group-Item die Werte und schreibt diese in das GroupDetail-Fragment.

• presentation.tags und JSP enthalten JSPs, welche das Layout und die HTML Struktur

enthalten. Sie sind direkt für die Darstellung zuständig und über die Fragmente von den

Items entkoppelt. Die JSPs sollen keine Logik enthalten. Entsprechende Anzeigelogik wird

deshalb in tag-Klassen ausgelagert (siehe 2.4.4). JSPs und tags sind die einzigen Elemente

des JCommSy in denen die Anzeigesprache HTML verwendet wird.

• presentation.servlet stellt mit den Servlets den zentralen Einstiegspunkt in das System

zur Verfügung. Das CommsyServlet nimmt die ankommende HTTP-Anfrage entgegen, wer-

tet diese aus und stößt den Aufbau des entsprechenden Ausstatter-Baums an. Das Servlet

selber greift auf Services und Items zu, z. B. um zu überprüfen, ob ein Benutzer angemeldet

ist.

• migration ist ein zusätzliches Package, dass eine Sonderrolle hat und deswegen nicht in der

Architektur auftaucht. Es enthält die Klassen, die dafür zuständig sind, dass das JCommSy

zusammen mit dem PCommSy betrieben werden kann. Dieses Package verschwindet, so-

bald das JCommSy alle Funktionalität des PCommSy enthält und darf dementsprechend von

keinem anderen Subsystem benutzt werden. Es enthält z. B. den MigrationFilter, einen

Servlet-Filter, der eine Umleitung ins PCommSy veranlasst, wenn eine Funktionalität ange-

fordert wird, die noch nicht vom JCommSy erbracht werden kann.

Im Rahmen der Umstrukturierung wurde die bereits teilweise umgesetzte Idee, die Service-Schicht

in Schnittstelle und Implementierung zu unterteilen, komplett umgesetzt. Dies vereinfacht die Be-

nutzung und kapselt die Hibernate-spezifischen Anteile.

Die zweite große Neuerung betrifft die Strukturierung des presentation-Packages. Die Auftei-

lung in die vier Subsysteme und die Anreicherung mit Informationen über erlaubte Beziehungen

hat folgende Vorteile. Es gibt einen technologieabhängigen (Servlet, JSP, Tags) und einen techno-

logieunabhängigen (Ausstatter, Fragmente) Teil. Da weder Ausstatter noch Fragmente von dem

technologieabhängigen Teil abhängen, können diese wiederverwendet werden, wenn die Techno-

logie ausgewechselt wird. Die Unterteilung vereinfacht die Weiterentwicklung – ein Entwickler

muss sich nicht mehr mit dem Servlet-Rahmenwerk auseinandersetzen, um die Ausstatter weiter

zu entwickeln. Die Ausstatter können aufgrund ihrer Unabhängigkeit vom Servlet-Rahmenwerk

einfacher getestet werden [Sch08b, S. 31].

Die Struktur und die Namen der Ausstatter- und Fragment-Klassen haben sich seit ihrer Einfüh-

Page 49: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

4.5 Zusammenfassung 37

rung (siehe [Hoh07]) gewandelt. Im Rahmen dieser Arbeit wurden die Package-Struktur bereinigt

und zusammen mit den Namen an die aktuelle Sicht auf das System angepasst.

4.4.2 Verletzungen

Die Ist-Architektur deckt sich weitgehend mit der Soll-Architektur. Eine Verletzung ist das leere

logic-Package. In diesem Package sollte Fachlogik enthalten sein. Dies beinhaltet z. B. Funktio-

nalität zum Überprüfen, ob die eingegebenen Werte eine gültige Ankündigung ergeben und deren

Speicherung in einem fachlichen Item. Diese Funktionalität ist über das System verteilt. Sie ist zu

großen Teilen in den Ausstattern und zum Teil implizit in den Servlets enthalten (siehe auch Abbil-

dung 6.1). Dies ist unerwünscht, da die Fachlogik unabhängig von der Anzeigelogik sein soll. Eine

Verzahnung beider macht es schwieriger, die Fachlogik mit einer alternativen Oberflächentechno-

logie wiederzuverwenden. Zusätzlich verkompliziert es die Entwicklung, da der Entwickler sich

mit zwei unabhängigen Aspekten gleichzeitig beschäftigen muss. Im Rahmen dieser Arbeit wer-

den Refactorings durchgeführt, deren Ziel es ist, die Fachlogik aus den Ausstattern zu extrahieren

und in eigenen Klassen im logic-Package verfügbar zu machen (siehe 6.1.2).

4.5 Zusammenfassung

Ziel der durchgeführten Architekturanalyse war es, die Ist- mit der Soll-Architektur zu verglei-

chen und dabei Schwachstellen, sowie daraus resultierende Änderungsvorschläge, zu identifizie-

ren. Durchgeführt wurde die Analyse mit dem Sotoarc. Der Sotoarc ist ein Programm, dass ein

Softwaresystem einliest, in einem Modell ablegt und dem Entwickler einen Blick auf das Sys-

tem auf einem höheren Abstraktionsniveau ermöglicht. Dafür wurden Subsysteme definiert, Re-

geln eingeführt wie die unterschiedlichen Subsysteme miteinander zusammenhängen und diese

dann am JCommSy validiert. Nötige Änderungen am JCommSy wurden identifiziert und umge-

setzt. Die resultierende Schichtenarchitektur des JCommSy, enthält insbesondere eine detaillierte

Unterteilung der Präsentationsschicht sowie eine explizite Schnittstelle der Service-Schicht. Als

ausstehendes Refactoring wurde das Extrahieren der Fachlogik in die Logik-Schicht identifiziert.

Page 50: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

38 Kapitel 4 Architekturanalyse

Page 51: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

39

Kapitel 5

Performance-Analyse

Wie in Abschnitt 2.2 ausgeführt, ist Performance ein Qualitätsmerkmal einer Software. Ziel die-

ses Kapitels ist es, einen Überblick über Performance-Aspekte des JCommSy zu erlangen und

Optimierungsmöglichkeiten dieses Qualitätsmerkmals zu identifizieren. Dafür wird der Vorgang

Performance-Analyse zunächst eingeführt. Es wird beschrieben mit welchem Ziel sie durchge-

führt wird, wie vorgegangen wird und welche Werkzeuge dabei eingesetzt werden. Abschließend

werden die Ergebnisse dargestellt und bewertet.

5.1 Ziel

Der Begriff Performance-Analyse beschreibt den Prozess, die Performance eines Systems zu un-

tersuchen, Änderungen zu identifizieren, umzusetzen und deren Auswirkungen zu erfassen. Das

Ziel dabei ist, die Performance (siehe Abschnitt 2.2) des Systems zu verbessern. Der Performance

stehen insbesondere die Architektur und die Lesbarkeit des Quelltextes gegenüber. Es ist nicht

das Ziel, die maximale Performance zu erreichen und dabei die Lesbarkeit des Quelltextes zu ver-

nachlässigen. Genausowenig sollen unüberlegt Architekturregeln verletzt oder verworfen werden,

nur um die Performance zu verbessern. Ziel ist es, eine Lösung zu finden, in der diese Aspekte

Beachtung finden. Dafür werden die Änderungen unter den verschiedenen Aspekten beleuchtet.

5.2 Vorgehen

Um die Performance-Analyse durchführen zu können, werden Software-Werkzeuge und das Sys-

tem, dass untersucht werden soll, benötigt. In diesem Abschnitt wird das System vorgestellt und

die nötigen Software-Werkzeuge eingeführt, wobei auf die besonderen Umstände einer Web-

Anwendung eingegangen wird.

5.2.1 Testumgebung

Um die Einflüsse durch äußere Faktoren so klein wie möglich zu halten, werden alle Performance-

Messungen auf einem eigens dafür eingerichteten Testsystem durchgeführt. Dieses Testsystem

wurde während dieser Diplomarbeit weder bezüglich der Hardware noch bezüglich der Software

verändert. Das JCommSy wird auf einem anderen System entwickelt und kompiliert. Das resul-

tierende Web Application Archive (kurz WAR) wird in den Tomcat des Testsystems geladen1. Die

WAR-Dateien werden archiviert, um alte Systemzustände erneut testen zu können.

1Das korrekte englische Wort ist „to deploy“.

Page 52: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

40 Kapitel 5 Performance-Analyse

Im Mittelpunkt dieser Arbeit stehen nicht die Aussagen über die absolute Leistung, sondern z. B.

darüber in welchen Bereichen der Anwendung Optimierungspotential liegt. Die Hardware rückt

damit in den Hintergrund. Da alle Leistungen letztendlich von der Hardware erbracht werden, darf

sie aber nicht ignoriert werden. Es folgt eine Beschreibung des Testsystems: Das Testsystem ent-

hält einen Intel Pentium 4 Prozessor mit 1,6 GHz Taktung, dem 1024 Megabyte Arbeitsspeicher

zur Verfügung stehen. Das verwendete Betriebsystem ist die Linux Distribution Kubuntu mit dem

Linux-Kernel Version 2.6.24. Die verwendete Java Virtual Machine ist die von Sun Microsys-

tems entwickelte HotSpot VM. Sie wird in Version 1.6.0_06 und im „Client Modus“ (siehe 2.2.8)

eingesetzt. Der verwendete Web-Server ist Apache Tomcat in Version 6.0.18 (siehe nächsten Ab-

schnitt).

5.2.2 Einflüsse des Tomcat

Die Web-Anwendung JCommSy läuft in einem Servlet-Container (siehe 2.4.2), dem Apache Tom-

cat2. Zusätzlich zur JVM muss der Tomcat erst hochgefahren werden. Beispielsweise werden die

verwendeten JSPs in Servlets übersetzt, wodurch der erste Zugriff auf eine JSP langsam ist. Im

regulären Betrieb, fallen diese Aktivitäten nicht mehr auf, da sie im Vergleich zur normalen, täg-

lichen Benutzung nur selten passieren. Aus diesem Grund, wird für das Analysieren folgende

Prozedur festgelegt:

1. Der Tomcat wird neu gestartet. Um sicher zu gehen, dass der Tomcat fertig gestartet ist,

werden 2 Minuten eingeplant. Typische Startzeiten auf dem Testsystem liegen bei 25 bis 55

Sekunden.

2. Der Benchmark wird einmal komplett durchlaufen. Dabei wird auf alle JSPs bereits einmal

zugegriffen und sämtliche Klassen und Einstellungsdateien werden geladen.

3. Der Benchmarking-Durchlauf wird zweimal durchgeführt. Diese zwei Durchläufe werden

gemessen.

Diese Prozedur hilft, die Einflüsse durch die Startphase der Anwendung zu minimieren und mög-

lichst aussagekräftige Messungen zu erhalten.

5.2.3 Testszenario

In diesem Unterabschnitt wird das Testszenario vorgestellt, anhand dessen die Performance des

JCommSy untersucht wird. Das JCommSy kann in seinem derzeitigen Zustand noch nicht ohne

das PCommSy die volle Funktionalität des CommSy anbieten (siehe 2.3.3). Der An- und Ab-

meldevorgang wird komplett vom PCommSy übernommen. Die Rubriken Gruppen, Termine und

Ankündigung sind in Java umgesetzt und werden für die Messungen verwendet.

Es wurden Arbeitsschritte mit dem JCommSy herausgesucht und mehrere zusammenhängende

Arbeitsschritte mit einem Namen zu einem Testfall zusammengefasst. Gemeinsam ergeben die

2http://tomcat.apache.org/

Page 53: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.2 Vorgehen 41

Testfälle das Benchmarking-Szenario, sie sind aber auch einzeln durchführbar. Ausgangspunkt je-

des Testfalls ist, dass der Benutzer angemeldet ist und einen Raum ausgewählt hat. Die Struktur

macht es möglich, bestimmten Testfällen mehr Gewicht zu geben, da einzeln spezifiziert werden

kann, wie oft ein Testfall ausgeführt wird. Es ist damit möglich, gezielt nur einen Testfall durch-

zuführen bzw. einen oder mehrere herauszunehmen.

Beim Zusammenstellen der Testfälle wurden folgende Aspekte in die Überlegungen mit einbezo-

gen: Die Testfälle sollen möglichst dem entsprechen, was Benutzer mit dem System machen und

Daten aus dem normalen Betrieb verwenden [Shi00, S. 13]. Es wurde versucht alle Funktionalitä-

ten des JCommSy in den Testfällen abzudecken. Dabei sollte das mehrmalige Abrufen der selben

Seite hintereinander in den Testfällen enthalten sein.

Folgende Testfälle wurden ausgearbeitet:

Übersichtsseiten simuliert das häufige Wechseln zwischen den Indexseiten. Es werden die an-

gegebenen Indexseiten in folgender Reihenfolge aufgerufen: Ankündigung, Termine, Grup-

pen, Gruppen, Termine, Ankündigung, Gruppen, Ankündigung.

Lesen beinhaltet das gezielte Auswählen von Einträgen und den Aufruf der zugehörigen Detail-

ansicht. Anschließend werden die nächsten 20 Einträge der Ankündigungsübersichtsseite

angefordert und eine Ankündigung ausgewählt. Abschließend wird in die Gruppenrubrik

gewechselt und dort eine Gruppe ausgewählt.

Bearbeiten enthält den Aufruf der Detail- und Bearbeitenseite einer Ankündigung, sowie den

Beitritt zu und Austritt aus einer Gruppe.

Erstellen/Löschen erstellt eine Ankündigung und speichert und löscht diese wieder. Anschlie-

ßend wird das gleiche in der Termine- und Gruppenrubrik gemacht.

Spezialfunktionen simuliert die Benutzung fortgeschrittener Funktionalitäten. Erst wird die An-

zahl der Einträge pro Seite auf 10 reduziert, anschließend werden alle vorhandenen Einträge

auf einer Seite dargestellt. Über die Suche-Funktionalität wird nach einer bestimmten Grup-

pe gesucht und diese angezeigt. Die Seite wird gespeichert und Informationen darüber, wer

die Seite zuletzt bearbeitet hat, werden abgerufen.

Sortieren sortiert die Übersichtsseiten nach unterschiedlichen Eigenschaften und in unterschied-

lichen Richtungen. Dies beinhaltet das Ändern der Sortierrichtung von absteigend nach auf-

steigend.

Die detaillierte Abfolge der einzelnen Schritte jedes Testfalls kann Anhang B entnommen wer-

den. In zwei der Testfälle, wird der Datenbestand geändert. Dabei wird darauf geachtet, dass der

Zustand, der nach dem Durchlauf vorliegt, dem davor entspricht. Eine erstellte Ankündigung wird

also wieder gelöscht. Im CommSy gelöschte Einträge werden als gelöscht markiert, verbleiben je-

doch in der Datenbank. Demzufolge verändert sich das System bei jedem Benchmark-Durchlauf

etwas. Die Datenbank enthält mehrere tausend, zum Teil gelöschte, Einträge. Durch die Profi-

lings wird sich die Größenordnung nicht ändern. Da die Größenordnung weit entfernt von den

Page 54: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

42 Kapitel 5 Performance-Analyse

möglichen 50.000.000 Einträge [MyS06] liegt, wird davon ausgegangen, dass die Datenbankzeit

höchstens linear mit der Anzahl der Einträge steigt. Der Fehler wird deshalb vernachlässigbar

klein sein.

5.3 Software-Werkzeuge

Um die Performance-Analyse durchzuführen, werden Software-Werkzeuge benötigt. JMeter wird

eingesetzt, um einen immer wieder durchführbaren Benchmark zur Verfügung zu haben. Das Pro-

filing der Anwendung wird mit Softwareunterstützung durchgeführt. In dieser Arbeit wird der

JProfiler vorgestellt und eingesetzt.

5.3.1 JMeter

Um die Performance des Systems messen zu können, müssen die Funktionen, die gemessen wer-

den sollen, ausgeführt werden. Im Fall des JCommSy, also einer Web-Anwendung, heißt das, dass

eine oder mehrere HTTP-Anfragen an das System gerichtet werden müssen. Damit diese Testan-

fragen nicht jedesmal von einem Menschen mit einem Web-Browser manuell ausgelöst werden

müssen, wird dies automatisiert. Es gibt eine Reihe von Möglichkeiten, entsprechend gestaltete

HTTP-Anfragen zu generieren. Im JCommSy werden HttpUnit-Tests eingesetzt, um die Oberflä-

che und deren Funktionalität zu testen. Mit HttpUnit könnten Testszenarien geschrieben werden

und als Benchmark ausgeführt werden. Der Nachteil dieses Vorgehens ist, dass diese Anfragen in

Java geschrieben werden müssen. Die Navigation erfolgt, indem die HTML-Struktur der Antwort

nach einem bestimmten Link durchsucht und ein Klick auf diesen simuliert wird. Es müsste also,

wie in den Testfällen, ein Ablauf wie in Quelltext 5.1 programmiert werden.

1 ...

2 // change to rubric "Gruppen"3 _currentPage = _currentPage.getLinkWith(RUBRICGROUP).click();

45 // goto detail page of group "TEST_GROUP_ROOM"6 _currentPage = _currentPage.getLinkWith(TEST_GROUP_ROOM).click();

78 // ensure that HTTP_USER_NAME is member9 WebLink link = _currentPage.getLinkWith(HTTP_USER_NAME);

10 assertNotNull("http unit user is not listed", link);

11 ...

Quelltext 5.1: Typischer Aufbau eines Tests mit HttpUnit

Diese Art von Tests, wie sie im JCommSy eingesetzt werden, haben den Vorteil, dass sie sich gut

mit den anderen Komponententests integrieren und diese in Form von Akzeptanztests abrunden

(siehe [Lin05, S. 5 f.] für Definitionen der unterschiedlichen Arten von Tests). Diese Art zu testen

ist allerdings fehleranfällig, aufwendig und langsam. Bereits das Umbenennen von Links kann

dazu führen, dass die Tests nicht mehr erfolgreich durchlaufen. Andererseits kann man detailliert

Page 55: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.3 Software-Werkzeuge 43

Abbildung 5.1: Ausschnitt aus der JMeter-Benutzungsoberfläche

überprüfen und dadurch sicherstellen, dass ein Link unter einem genau vorgegebenen Namen vor-

handen ist. Dies ist gerade im Fall des JCommSy von Bedeutung, da mit dem PCommSy eine

Vorlage vorhanden ist, die möglichst genau nachgebaut werden soll.

Um ein Szenario für ein Benchmark zu definieren, ist dieses Vorgehen umständlich und unnö-

tig. Bei einem Benchmark geht es nicht um die Struktur der ausgelieferten Seite, sondern darum

eine Abfolge von HTTP-Anfragen an das System zu definieren. Mit dem Werkzeug Apache JMe-

ter3 können über eine grafische Benutzungsoberfläche Testpläne zusammengestellt werden. Diese

bestehen aus einer Reihe von HTTP-Anfragen. Für jede einzelne Anfrage (oder mehrere gemein-

sam) besteht die Möglichkeit HTTP-Parameter, Zieladresse und weitere Eigenschaften zu setzen.

JMeter ermöglicht es, diese Anfragen zu gruppieren, wiederholt auszuführen, zufällige Pausen

einzufügen und die Antworten auszuwerten. Ein Ausschnitt der JMeter-Oberfläche ist in Abbil-

dung 5.1 zu sehen.

Darüber hinausgehend bietet JMeter Möglichkeiten, das Antwortverhalten zu beobachten und

zahlreiche Daten zu erfassen, z. B. die durchschnittliche Antwortzeit auf eine Anfrage. Diese Er-

gebnisse können grafisch oder tabellarisch aufbereitet angezeigt und protokolliert werden. Mit

Hilfe der „HTTP Proxy Server“-Funktionalität ist es möglich, mit einem herkömmlichen Web-

Browser durch eine Web-Seite zu navigieren und alle HTTP-Anfragen, die dabei ausgelöst wer-

den, von JMeter mitprotokollieren zu lassen. Beim CommSy können aufgrund von Einschrän-

kungen, die durch die Verwendung von Sitzungen entstehen, nicht einfach alte Anfragen erneut

3http://jakarta.apache.org/jmeter/

Page 56: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

44 Kapitel 5 Performance-Analyse

gesendet werden. Mit wenigen Anpassungen können die aufgenommenen Anfragen allerdings

CommSy-kompatibel gemacht werden. Die einzelnen Anfragen können benannt und mit Kom-

mentaren versehen werden. Somit können sie einfach identifiziert, kopiert und wiederverwendet

werden. Die in der Abbildung 5.1 ausgewählte und angezeigte HTTP-Anfrage entspricht der, die

ausgelöst wird, wenn man auf die Gruppen-Rubrik klickt und fordert deren Index-Seite an.

5.3.2 JProfiler

In dieser Arbeit kommt der Profiler JProfiler4 von ej-technologies zum Einsatz. Mit dem JPro-

filer kann man in Java geschriebene Anwendungen untersuchen. Dafür wird mittels Bytecode-

Instrumentierung der auszuführende Bytecode verändert und entsprechend die Aufrufe protokol-

liert, Speicherbelegungen abgefragt und Ausführungszeiten ermittelt (siehe auch 2.2.7). Der JPro-

filer besteht aus zwei logischen Komponenten. Eine Komponente muss auf demselben Rechner

laufen, auf dem die zu analysierende Software läuft. Das Startskript der Anwendung wird so an-

gepasst, dass es der JVM den JProfiler als Profiling-Agent übergibt. Standardmäßig wartet diese

Komponente darauf, dass die JProfiler-Oberfläche sich mit ihr verbindet. Die Oberfläche ist die

zweite Komponente und kann auf einem anderen Rechner laufen. Dies hat z. B. den Vorteil, dass

die Arbeit mit der Oberfläche, den Prozessor auf der zu analysierenden Maschine nicht bean-

sprucht und damit die Ergebnisse nicht beeinflusst.

In der JProfiler-Benutzungsoberfläche erstellt oder lädt der Benutzer eine „Session“. Diese enthält

Informationen, wo die wartende Profiling-Komponente liegt, welche Profiling-Optionen aktiviert

sind und welche Klassen herausgefiltert werden sollen. Wird die Session gestartet, verbindet sich

die JProfiler-Oberfläche mit der Profiling-Komponente und übergibt dieser die gewählten Ein-

stellungen. Diese startet entsprechend die Anwendung. Der JProfiler erhält zu diesem Zeitpunkt

bereits Informationen über das laufende System und kann diese anzeigen.

Der JProfiler bietet fünf grundlegend unterschiedliche Ansichtenkategorien an, welche wiederum

unterschiedliche Ansichten enthalten.

Die „Memory Views“ liefern u. a. Informationen von welcher Klasse es am meisten Objekte gibt,

welche Methoden am meisten Objekte erzeugen und wo innerhalb der Anwendung Objekte einer

Klasse erzeugt werden.

Der „Heap Walker“ erlaubt es, ein Speicherabbild der Anwendung zu erstellen und dieses genauer

zu analysieren. Dafür werden Informationen extrahiert, wie z. B. von welcher Klasse wie viele

Objekte existieren. Man kann Informationen darüber erhalten, welche Objekte welche anderen

Objekte referenzieren und auf diese Weise durch den Speicher navigieren.

Die „CPU Views“ liefern Informationen darüber, in welchen Methoden das Programm wieviel

Zeit verbringt. Dabei kann der JProfiler die Informationen auf unterschiedliche Arten darstellen

und in einer Hotspots-Ansicht mit der Anzahl der Aufrufe zusammenbringen.

In den „Thread Views“ werden Informationen zu den einzelnen Threads dargestellt. Welcher

Thread wartet auf welchen Monitor, welcher Thread ist gerade aktiv, wo kommt es zu einem

4http://www.ej-technologies.com/products/jprofiler/overview.html

Page 57: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.3 Software-Werkzeuge 45

Abbildung 5.2: Benutzungsoberfläche des JProfiler

Deadlock – dies sind Fragen, bei deren Beantwortung diese Ansichten helfen.

Die „VM Telemetry Views“ informiert über die aktuelle Speichersituation der JVM, darüber wann

der Garbage Collector aktiv wird, wieviele Klassen geladen sind und wie groß die Gesamtauslas-

tung des Prozessors ist.

Die Benutzungsoberfläche des JProfiler ist in Abbildung 5.2 zu sehen. Die dort abgebildete An-

sicht zeigt, welche Klassen wieviel Prozent der Ausführungszeit benötigen, wie lange ihre Metho-

den durchschnittlich ausgeführt werden und wie oft ihre Methoden aufgerufen werden.

Der JProfiler bietet die Möglichkeit Filter zu spezifizieren, die festlegen welche Klassen in die

Messungen mit einbezogen werden. Ohne Filter würden die Klassen der Bibliotheken, beispiels-

weise java.lang.String, mit betrachtet werden. Dies hätte zur Folge, dass die Ausgabe sehr lang

und damit unübersichtlich würde. Außerdem interessiert es Anwendungsentwickler selten wie per-

formant die Methoden aus der Standardbibliothek sind, da sie keinen Einfluss darauf haben. Ein

weiterer Aspekt, der gegen das Profiling aller Klassen spricht, ist, dass dadurch die gesamte An-

wendung signifikant langsamer laufen würde. Durch das Profiling entsteht ein Mehraufwand, der

mit der Anzahl der betrachteten Klassen zunimmt.

Mit einem Filter lässt sich beispielsweise spezifizieren, dass nur die Klassen aus dem Package

de.unihamburg.informatik.jcommsy und allen darin enthaltenen Packages5 betrachtet werden.

Alle anderen Klassen werden dann von JProfiler nicht gemessen. Allerdings werden alle Auf-

5Das Enthaltensein ist über die Namensstruktur von Packages definiert (siehe 2.1.1).

Page 58: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

46 Kapitel 5 Performance-Analyse

rufe aus einer nicht gefilterten Klasse immer mit aufgeführt. Dies wird an folgendem Beispiel

verdeutlicht. Angenommen die Klasse Announcement wird gemessen, aber java.util.Date und

java.lang.String sind durch einen Filter ausgeschlossen. Weiter angenommen, Announcement

ruft an Date die Methode toString auf, dann wird diese Methode noch von JProfiler mit ihren

Zeiten aufgeführt. Die Tatsache, dass toString bei der Ausführung noch eine Methode an String

aufruft, wird vom Profiler nicht mehr registriert.

Mit Hilfe von Triggern (Auslösern), kann der Profiler so eingestellt werden, dass er automatisch

auf bestimmte Ereignisse reagiert. Auslösende Ereignisse können z. B. der Aufruf einer Metho-

de oder das Übersteigen eines bestimmten Speicherfüllstands sein. Über Aktionen kann definiert

werden, wie der JProfiler beim Eintreten des Ereignisses reagiert. Beispielsweise könnte ein Spei-

cherabbild erstellt werden oder der Speicherfüllstand in die Log-Datei geschrieben werden. Um

das Starten der Profiling-Aktivitäten auf einen Zeitpunkt nach dem Start des Tomcat zu verschie-

ben, wird ein zeitlicher Trigger verwendet, der nach zwei Minuten die Aktion „Start recording“

auslöst.

5.3.3 Alternativen

Neben dem hier eingesetzten JProfiler gibt es weitere Profiler für Java-Anwendungen. Ähnlichen

Funktionsumfang wie der JProfiler haben JProbe6 und YourKit7. Alle drei ermöglichen das Mes-

sen der Ausführungszeiten der einzelnen Methoden und unterstützen das Finden von Hotspots

(siehe 2.2.7). Das Speichermanagement wird von allen beobachtbar gemacht und es gibt Unter-

stützung beim Finden von Speicherlecks. Alle drei unterstützen sowohl Java 5 als auch Java 6 und

lassen sich in Entwicklungsumgebungen einbinden, insbesondere in die im Rahmen des JComm-

Sy eingesetzte Entwicklungsumgebung Eclipse8.

Das von Quest Software entwickelte JProbe erlaubt, neben dem Profiling, die Testabdeckung zu

messen. Somit kann festgestellt werden, welche Quelltextzeilen während der Komponententests

nicht durchlaufen und somit nicht getestet werden. Im JCommSy kommt dafür Cobertura9 zum

Einsatz. Dieser Aspekt der Softwarequalität wird in dieser Arbeit jedoch nicht betrachtet.

Die Software YourKit stellt neben einem Java Profiler auch einen Profiler für die .NET Umge-

bung zur Verfügung. Insbesondere wenn absehbar nicht nur Java Anwendungen analysiert werden

sollen, kann durch die Verwendung von YourKit eine doppelte Einarbeitung vermieden werden.

YourKit ermöglicht Profilings von Anwendungen, die mittels Java Micro Edition (J2ME) für mo-

bile Geräte entwickelt sind.

Zu JMeter gibt es ebenfalls Alternativen. Die Anwendung The Grinder10 ermöglicht das Erstellen

von Lasttests für unterschiedliche Schnittstellen. Neben Remote Method Invocation (RMI), Web-

6http://www.quest.com/jprobe/7http://www.yourkit.com/8http://www.eclipse.org/9http://cobertura.sourceforge.net/

10http://grinder.sourceforge.net/

Page 59: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.4 Betrachtungsebenen 47

Services und weiteren, können insbesondere HTTP-Anfragen generiert werden. Diese können be-

nutzt werden, um das Verhalten von Web-Servern bei steigenden Anfragezahlen zu untersuchen.

5.4 Betrachtungsebenen

Die Architektur einer Software ist nicht ohne weiteres aus der Quelltext-Repräsentation heraus-

zulesen. Aus dem Quelltext wird zwar deutlich, welche Klasse zu welchem Package gehört, aber

bereits die Zuordnung zu einer Schicht, ist nicht mehr ersichtlich. Im Gegensatz dazu, findet man

einen Programmabschnitt, der in einer Schleife eine Reihe von mathematischen Operationen aus-

führt, direkt im Quelltext wieder. Es gibt also unterschiedliche Ebenen, auf denen man eine Soft-

ware betrachten und analysieren kann. Dies gilt auch für die Performance-Analyse. Eine Schleife

findet sich direkt im Bytecode wieder und kann mit einem Profiler gemessen werden. Für einen

Profiler existieren keine Schichten und es gibt keine Zuordnung der Klassen zu einer Schicht.

Dementsprechend ist es schwieriger die Performance auf die Architektur-Ebene abzubilden. Zwi-

schen diesen beiden Ebenen liegt noch die Ebene des Zusammenspiels verschiedener Klassen.

Auf Muster bezogen werden die drei Ebenen, als Architekturmuster, Entwurfsmuster und Idiome

bezeichnet [RH06, S. 342 ff.].

Die gröbste Ebene, die in dieser Arbeit eingenommen wird, ist die Architekturebene. Die einzel-

nen Artefakte sind dann Architekturelemente, wie z. B. eine Schicht. Es stellt sich die Frage, ob

die Verwendung einer Schichtung Auswirkungen auf die Performance hat, und wenn ja, welche.

Da diese Ebene nicht direkt gemessen werden kann, muss entsprechend aggregiert werden.

Auf der Ebene der Entwurfsmuster wird das Zusammenspiel verschiedener Klassen in den Mittel-

punkt gerückt. Durch die Verwendung von Entwurfsmustern (siehe [GHJV95]) wird die Flexibi-

lität des Systems erhöht. Viele Entwurfsmuster basieren darauf, dass zusätzliche Objekte benötigt

werden und die Aufgaben durch Delegation umverteilt werden. Im JCommSy wird beispielsweise

eine Composite-Struktur für die Fragmente und Ausstatter genutzt. Die Verwendung von Ent-

wurfsmustern hat Auswirkungen auf den benötigten Speicher und die zeitliche Performance der

Anwendung. Demgegenüber steht eine klarer strukturierte Anwendung, deren Quelltext sich bes-

ser kommunizieren und verändern lässt. Entwurfsmuster betreffen in der Regel einzelne Subsys-

teme und sind unabhängig von der Anwendungsdomäne.

Auf feinster Ebene besteht die Möglichkeit den Quelltext innerhalb einer Methode oder Klasse zu

optimieren, z. B. indem eine häufige Konkatenation von Strings mittels Plus-Operator vermieden

wird [BGWA08, S. 227]. Die Java-Klasse StringBuilder ersetzt dies performanter. Die Lesbar-

keit des Quelltextes wird dadurch beeinflusst. Eine Optimierung auf dieser Ebene ändert nur eine

einzelne Methode und hat keine Auswirkungen auf andere Methoden (siehe [Shi00] und [Bul00]).

Im Gegensatz zu den beiden anderen Ebenen, haben die Idiome einen direkten Bezug zu konkreten

Problemsituationen der Entwickler und sind deshalb häufig an eine Anwendungsdomäne und/oder

eine Programmiersprache gebunden. Analog sind Optimierungen auf dieser Ebene spezifisch für

die Anwendungsdomäne und die Programmiersprache.

Page 60: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

48 Kapitel 5 Performance-Analyse

Alle drei Ebenen werden in dieser Arbeit betrachtet. Um sie etwas klarer abzugrenzen, wird im

Folgenden für jede eine Reihe von Ansatzpunkten aufgeführt. Um die Performance-Skala fassba-

rer zu machen, werden zunächst Performance-Kategorien eingeführt und die Bausteine der Pro-

grammierung diesen zugeordnet.

5.4.1 Performance-Kategorien und -Bausteine

Während der Untersuchungen konnten Aspekte in unterschiedlichen zeitlichen Größenordnungen

identifiziert werden. Um diese handhabbar zu machen, werden fünf Kategorien eingeführt.

Die kleinsten von Profilern erfassten Einheiten sind Methoden. Sie setzen sich aus einfachen Java-

Konstrukten, wie Zuweisungen oder elementaren Berechnungen, zusammen. Diese bilden die ers-

te Kategorie auf der Performance-Skala. Einfache Methoden, wie Setter- oder Getter, fallen eben-

falls in diese Kategorie.

Standardmethoden können bereits von Profilern erfasst werden und bauen auf den elementaren

Konstrukten auf. Sie enthalten Funktionalitäten die Entwicklern ähnlich elementar erscheinen wie

die Java-Konstrukte.

Darauf aufbauend sind Schleifen und Rekursionen als Konstrukte aufgefallen. Schleifenkörper

enthalten wiederum Elemente der beiden kleineren Kategorien. Da Schleifen in der Regel dafür

gemacht sind, häufig durchlaufen zu werden und nicht nur Kategorie I-Aspekte enthalten, bilden

sie Kategorie III.

Ein- und Ausgabe-Operationen, wie Festplattenzugriffe oder Netzwerkkommunikationen, bilden

die nächste Kategorie, die sich wiederum durch deutlich größere Zeiten auszeichnet.

Als Kategorie V wurden Algorithmen identifiziert. Sie bestehen aus Elementen der unteren Kate-

gorien und bringen diese zu einem komplexen Gebilde zusammen, dass als Einheit wahrgenom-

men wird.

Zusammengefasst ergeben sich folgende fünf Kategorien.

I Java-Konstrukte: 10 Nanosekunden

II Standardmethoden: 1 Mikrosekunde

III Schleifen: 100 Mikrosekunden

IV Ein-/Ausgabe: 10 Millisekunden

V Algorithmen: > 100 Millisekunden

Die angegebenen Größen stellen den Mittelpunkt der Kategorien dar, wobei sich eine Kategorie

über den Bereich von 2 Zehnerpotenzen erstreckt (siehe Abbildung 5.3). Beispielsweise reicht Ka-

tegorie I von einer bis zu 100 Nanosekunden. Die Einteilungen sind nicht immer eindeutig. Eine

Schleife, die nur einmal durchlaufen wird, kann auch in Kategorie I oder II fallen. Besonders die

Kategorie V ist unscharf, da die Ausführungszeiten von Algorithmus zu Algorithmus unterschied-

lich sind. Die Einteilung soll nicht aussagen, dass es keine Algorithmen gibt, die in Kategorie II

fallen, sondern sie sagt aus, dass Algorithmen durchaus Zeiten im Bereich von 100 Millisekunden

Page 61: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.4 Betrachtungsebenen 49

erreichen können.

Die folgende Aufzählung enthält grundlegende Bausteine mit ihren Beschreibungen und ordnet

sie den Kategorien zu. Die Bausteine sind nicht unabhängig voneinander, da die komplexeren

die einfacheren einsetzen und beinhalten. Sie werden vom Entwickler als eigenständige Einhei-

ten wahrgenommen und deswegen hier aufgeführt. Die Bausteine werden in die fünf Kategorien

eingeordnet:

Kategorie I:• Anweisung: Anweisungen, wie das Zuweisen einer Variablen oder die Addition zweier pri-

mitiver Datentypen, sind die kleinsten Bausteine.

• Sprung/Bedingung: Das Auswerten einer bedingten Anweisung oder ein Sprung, wie er in

einer Schleife benötigt wird.

• Methodenaufruf: Der Aufruf einer Methode, inklusive der Manipulation des Stacks.

• Objekterzeugung: Die Allokation von Speicher, z. B. das Erzeugen eines neuen Objekts.

• Indirektion: Das Erzeugen eines Objekts und das Aufrufen einer Methode an diesem.

Kategorie II:• Standard-Methode: Standard-Implementierungen von equals bzw. toString, wie sie z. B.

String bzw. Object vorgeben. Diese Methoden enthalten Algorithmen, befinden sich jedoch

sowohl aus Sicht des Entwicklers, als auch aus Performance-Sicht auf einer anderen Ebe-

ne als vom Entwickler selbst implementierte komplexe Algorithmen. Standard-Methoden

können vom Entwickler nicht verändert werden und bilden die Kategorie II.

Kategorie III:• Schleife/Rekursion: Abhängig von der Anzahl der Durchläufe, unterliegen sie einer breiten

Schwankung. Eine Schleife in der 10.000 Objekterzeugungen stattfinden landet in der Kate-

gorie III. Schleifen und Rekursionen enthalten in der Regel Kategorie II-Aspekte und wer-

den vielfach durchlaufen. Deshalb sind sie eine Kategorie höher als die Standard-Methoden

einzuordnen.

• Ein-/Ausgabe-Operation auf Dateien im Cache: Lese- und Schreibzugriffe auf Dateien

die sich im Cache befinden.

• lokale Socketverbindung: Socketverbindungen zum eigenen Rechner, z. B. um mit einem

anderen Prozess zu kommunizieren.

Kategorie IV:• Dateizugriff: Der Zugriff auf eine Datei auf der Festplatte, die nicht im Cache liegt.

• Datenbankanfrage: Zugriff auf eine Datenbank.

• Socketverbindung: Verbindung zu einem anderen Rechner im Netzwerk.

Page 62: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

50 Kapitel 5 Performance-Analyse

Kategorie V:• Algorithmus: Ein Algorithmus der aufwendige Berechnungen durchführt und/oder die obe-

ren Aspekte beinhaltet.

Eine detailliertere Beschreibung der Ausführungszeiten der Bausteine ist Abbildung 5.3 zu ent-

nehmen. Diese Daten wurden mit Mikro-Benchmarks erhoben, die mittels einer angepassten Ver-

sion von JFreeProfilingCenter11 durchgeführt wurden. Auch wenn die exakten Messwerte und die

genaue Position der Kategorien auf unterschiedlichen Rechnern verschoben sind, so bleibt die

prinzipielle Einteilung und Unterteilung in die Kategorien bestehen.

1 10 100 1.000 10.000 100.000 1.000.000 10.000.000 100.000.000 [ns]Ausführungszeiten in Nanosekunden (logarithmische Darstellung)

einz

elne

Anw

eisung

enMetho

dena

ufruf

Objekterzeu

gung

Entwurfsmuster/zu

sätzliche

Indirektion

Equa

ls-Vergleich

vonzw

eiSt

ring

s

toSt

ring

vonOb

ject

Synchron

isation(2

Thread-Wechsel)

Schreibe

nin

eine

gecachte

Datei

Schleife/R

ekursion

:10

.000

Objekte

erzeug

enSo

cketverbindu

ng(selbe

rRechn

er)

JDBC

Datenba

nkan

frag

e(selbe

rRechn

er)

Socketverbindu

ng(L

AN)

Zugriff

aufObjekte

ausDB

über

Hiberna

teLe

seneine

run

gecachtenDatei

Sortiereneine

s1.00

0.00

0int-Arrays

IJava-Konstrukte

IIStandardmethoden

IIISchleifen

IVEin-/Ausgabe

VAlgorithmen

Nanosekunden Mikrosekunden Millisekunden

Abbildung 5.3: Gegenüberstellung von Ausführungszeiten und Einteilung in die Kategorien

Bevor die Ergebnisse der Analyse vorgestellt werden, werden zunächst die Betrachtungsebenen

detaillierter vorgestellt.

5.4.2 Innerhalb einer Klasse

Bereits innerhalb der untersten Betrachtungsebene können unterschiedliche Arten von Optimie-

rungen gemacht werden. Vorschläge für Aspekte, die untersucht werden können, fangen bei ele-

mentaren Anweisungen an und enden auf der Ebene des Entwurfs von Klassen. Unter dem Be-

griff „strength reduction“ versteht man die Verwendung schnellerer Befehle, z. B. kann x = x + 5

durch x += 5 ersetzt werden (siehe [Shi00, S. 76]). Eine Gegenüberstellung der Performance des

ternären Operators12 mit einem „if-then-else“-Konstrukt ist eine weitere Möglichkeit, auf dieser

feinsten Ebene, Performance zu betrachten. Diese Aspekte betreffen die Kategorie I.

Das Verwenden alternativer Algorithmen wird in der Regel auf dieser Ebene anzuordnen sein,

11http://sourceforge.net/projects/jfreeprofcenter/12Der Bedingungsoperator A ? B : C hat 3 Operanden und liefert B, falls A wahr ist und sonst C.

Page 63: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.4 Betrachtungsebenen 51

kann jedoch auf der nächst höheren Ebene betrachtet werden. Dies passiert z. B. wenn unterschied-

liche Algorithmen als unterschiedliche Strategien nach Gamma [GHJV95] realisiert werden und

so zur Laufzeit auswechselbar sind.

Das häufige Konvertieren von Daten kann zu Performance-Problemen führen. Wird bei jedem Zu-

griff z. B. zwischen String und Integer konvertiert, kann untersucht werden, ob die Klasse nicht

anders hätte entworfen werden können.

Ein weiterer Aspekt dieser Ebene betrifft die Verwendung von Bibliotheken. Durch die korrekte

Benutzung der richtigen Klassen und Methoden kann die Performance gesteigert werden. Bei-

spielsweise stellt Bulka fest, dass die Verwendung von String.equalsIgnoreCase mehr als eine

Zehnerpotenz schneller ist, als wenn erst String.toLowerCase und dann String.equals benutzt

wird [Bul00, S. 10]. Alle drei Methoden sind in Kategorie II einzuordnen und die Verbesserung

also innerhalb einer Kategorie.

5.4.3 Zusammenspiel von Klassen

Diese Betrachtungsebene ist, wie die anderen beiden auch, nicht nur in der Objektorientierung zu

finden. Im Rahmen dieser Arbeit werden andere Programmierparadigmen jedoch nicht betrachtet.

Objektorientierung resultiert in einem Netz von Objekten mit vielen kleinen Methoden. Dabei

wird insbesondere Polymorphismus eingesetzt und damit zur Laufzeit ermittelt, welche Methode

aufgerufen werden soll. Dies verursacht Kosten, insbesondere, da die Prozessoren für statisch fest-

gelegte Methodenaufrufe optimiert sind [Shi00, S. 2]. Auf dieser Ebene kann betrachtet werden,

inwiefern sich die zusätzlichen Klassen und Methoden eines Entwurfsmusters auf die Performance

der Anwendung auswirken. Generell lässt sich nicht sagen, dass Objektorientierung oder Verer-

bung schlecht oder gut für die Performance sind. Es hängt davon ab, wie sie eingesetzt werden.

Richtig eingesetzt, kann Polymorphie z. B. „if-else“-Konstrukte unnötig machen und damit die

Performance steigern [Bul00, S. 91]. Die Verwendung von Interfaces und die Implementierung

gegen Interfaces ermöglicht es, die Implementierung zu kapseln und so austauschbar zu halten.

Die Verwendung von Fabrikmustern [GHJV95] zur Erzeugung von Objekten resultiert in zusätzli-

chen Laufzeitkosten (siehe [Shi00, S. 378]). Wie groß diese Kosten sind, bzw. an welchem Punkt

es sich lohnt auf Entwurfsmuster zu verzichten, wird auf dieser Ebene betrachtet und untersucht.

Objekte können einen Zustand haben und diesen ändern. Wenn ein Objekt zustandslos ist oder

seinen Zustand nicht ändern kann (also unveränderlich ist), dann kann das Objekt wiederverwen-

det werden und muss nicht neu erzeugt werden. Bei veränderlichen Objekten ist es eine wichtige

Entwurfsentscheidung, ob ein Objekt wiederverwendet wird oder ein neues Objekt erzeugt wird.

Letzteres führt in der Regel zu besser lesbarem Quelltext und vermeidet Fehler.

5.4.4 Architekturelemente

Auf der Architekturebene gibt es unterschiedliche Ansätze, Performance zu betrachten. Die direk-

ten Auswirkungen durch die Regeln einer Architektur sind ein Betrachtungspunkt. In einer strikten

Schichtenarchitektur dürfen Klassen einer Schicht nicht an einer anderen Schicht vorbei auf wei-

Page 64: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

52 Kapitel 5 Performance-Analyse

ter unten liegende Schichten zugreifen. Im einfachsten Fall mag es nötig sein, in der zwischen

zwei Schichten liegenden Schicht eine Klasse anzubieten, die die Anfrage weiter durchreicht. Das

Resultat dieses Vorgehens ist ein zusätzlicher Methodenaufruf. Die Auswirkungen auf die Perfor-

mance können untersucht und bewertet werden.

Eine weitere Herangehensweise ist das Aggregieren von Performance-Informationen auf Archi-

tekturebene. Es kann ermittelt werden, welche Subsysteme welche Anteile der gesamten Ausfüh-

rungszeit einer Anwendung benötigen und wieviel Speicher dabei jeweils angefordert wird. Diese

Herangehensweise bietet die Möglichkeit, den Bereich, in dem die Anwendung optimiert wer-

den soll, einzugrenzen, um z. B. gezielt eine Bibliothek durch eine andere zu ersetzen. Es können

Informationen gewonnen werden, die es erlauben Architekturregeln zu überdenken oder neue ein-

zuführen. Erst wenn bekannt ist, wie das Laufzeitverhalten einzelner Komponenten ist, können

die Auswirkungen einer Aufteilung der Komponenten auf unterschiedliche Rechner abgeschätzt

und bewertet werden. Dies kann auf Grundlage der eingeführten Kategorien passieren. Wenn die

Anwendungslogik die meiste Zeit auf die Datenbank wartet, dann bringt es kaum Geschwindig-

keitsvorteile die Anwendungslogik auf mehreren Rechnern ausführen zu lassen.

Zu der Architektur einer Anwendung kann die Festlegung von Zuständigkeiten gehören. Werden

Services per Dependency Injection (siehe 2.4.6) in den sie benutzenden Klassen verfügbar ge-

macht, dann kann untersucht werden, was dieser Mechanismus an Performance kostet oder bringt.

Dependency Injection kann z. B. verhindern, dass die Services öfter als nötig erzeugt werden und

erst dann, wenn sie benutzt werden. Wird dieser Mechanismus umgangen, hat das Auswirkungen

auf die Performance und die Architektur.

Regeln für die Benutzung einer Datenbank haben unmittelbar Auswirkungen auf die Performance.

Die Verwendung eines objektrelationalen Mappers kapselt einige Aspekte, andere hingegen müs-

sen weiterhin beachtet werden. Es sollte versucht werden, die Zeit, die in einer Transaktion ver-

bracht wird, zu minimieren und z. B. lange Transaktionen in mehrere kurze aufzuteilen [Shi00,

S. 368]. Auch wenn ein OR-Mapper Verbindungen zur Datenbank bereithält und wiederverwen-

det, muss beachtet werden, wie dieser zu benutzen ist, um das unnötige Öffnen und Schließen von

Verbindungen zu verhindern.

Auf der Architekturebene werden auch Nebenläufigkeit und Parallelität betrachtet. Durch die ne-

benläufige Ausführung kann die Performance gesteigert werden, jedoch wird dadurch die Software

und deren Entwicklung komplexer. Es ist schwierig Nebenläufigkeit nachträglich hinzuzufügen.

Sie sollte von Anfang an mit eingeplant werden und in den Bereichen, in denen sie nicht erwünscht

ist, durch Synchronisation verhindert werden [Shi00, S. 370].

Das Verhalten der Anwendung unter Last und ihre Fähigkeit zu skalieren sind zwei weitere Aspek-

te von Performance. Sie beziehen sich stets auf das Zusammenspiel der Subsysteme, betreffen das

System als ganzes und können nur auf der Architekturebene betrachtet werden. Sie werden in

dieser Arbeit nicht behandelt.

Page 65: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.5 Performance des JCommSy 53

5.5 Performance des JCommSy

Die bisherigen Abschnitte dieses Kapitels haben das Vorgehen bei einer Performance-Analyse be-

schrieben und die dafür nötigen Werkzeuge eingeführt. Es wurden die Ebenen definiert, auf denen

Performance Aspekte betrachtet werden können. Zusätzlich wurden fünf Performance-Kategorien

eingeführt.

In diesem Abschnitt werden die Ergebnisse verschiedener Aspekte der Performance des JComm-

Sy vorgestellt. Grundlage dafür ist die Version des JCommSy zu Beginn dieser Arbeit. Wie bei der

Architekturanalyse, leiten sich aus dieser Analyse Optimierungsmöglichkeiten ab. Diese Optimie-

rungen werden im nächsten Kapitel beschrieben, durchgeführt und deren Ergebnisse analysiert.

Die ersten Messungen am JCommSy lieferten das Ergebnis, dass die Anwendung 28 Prozent der

Zeit in dem Package apache.log4j verbringt. Dieses Package stellt Protokollierungsfunktionali-

tät in Form von „Loggern“ zur Verfügung. Im JCommSy wird das Logging an vielen Stellen zur

Ausgabe von Debug-Informationen verwendet. Beispielsweise wird in den Logger geschrieben,

ob ein Benutzer angemeldet ist. Der Logger ist so eingestellt, dass er die Informationen in einer

Datei auf der Festplatte ablegt, wodurch die langen Ausführungszeiten entstehen. Für den realen

Betrieb wird das Logging in der Regel auf Ausgaben der Stufe Warnung oder höher eingestellt

sein. Konfiguriert man den Logger entsprechend, benötigt der Logger nur noch vernachlässigbar

wenig Zeit. Für alle weiteren Tests, wird der Logger auf der Stufe Warnung verbleiben.

5.5.1 Zeitliche Performance

In diesem Abschnitt wird die zeitliche Performance des JCommSy untersucht und dargestellt.

Zunächst passiert dies aus Sicht eines Benutzers, anschließend detaillierter mittels Profiling auf

dem Server. Die Ergebnisse werden auf Ebene der Schichtenarchitektur dargestellt. Analysiert

wird hier das JCommSy in der Version von Oktober 2008 und somit in dem Zustand vor den

durchgeführten Optimierungen.

Messung beim Client

Zunächst einmal werden die durchschnittlichen Antwortzeiten dargestellt, wie JMeter sie auf-

zeichnet. Diese Zeiten wurden gewonnen, ohne das ein JProfiler nebenbei die Anwendung misst.

Die Ergebnisse entsprechen in einer Näherung dem, was der Benutzer des JCommSy wahrnehmen

würde, bis auf die Tatsache, dass das eigentliche Darstellen des Ergebnisses im Browser zusätzlich

Zeit benötigt. Die Messung zeigt, dass Anfragen, die eine Detail- oder Editieransicht betreffen, bei

ca. 260 bzw. 120 ms liegen. Das Speichern und Erzeugen von neuen Ankündigungen, Gruppen und

Terminen gehört in die Editieransicht-Kategorie. Die Indexseiten brauchen mit ca. 400 bis 700 ms

deutlich länger. Hierbei fällt auf, dass Ankündigungen mit ca. 700 ms deutlich langsamer sind, als

Gruppen mit ca. 410 ms. Zu den langsamen Aktionen gehört das Löschen von Einträgen (ca. 620

ms), sowie das Sortieren der Listen mit ca. 800 ms. Über alle Anfragen des Benchmarks gemit-

telt, ergibt sich ein Durchschnitt von ca. 400 ms pro Anfrage. Detaillierte Ergebnisse können im

Anhang in Abbildung A.1 gefunden werden.

Page 66: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

54 Kapitel 5 Performance-Analyse

Schicht Zeit in ms Anteil in %service 143.990 ms 35,13 %util 141.000 ms 34,40 %presentation 83.682 ms 20,41 %item 35.798 ms 8,73 %domainvalue 3.889 ms 0,95 %migration 1.566 ms 0,38 %logic 0 ms 0 %Gesamt 409.925 ms 100 %

Tabelle 5.1: Laufzeiten der Schichten (Stand: 14. Oktober 2008)

Laufzeiten pro SchichtDie folgende Darstellung gibt Aufschluss darüber, in welchen Schichten des JCommSy welche

Anteile an Zeit verbraucht werden. Da die Schichten nicht dem Quelltext oder dem Bytecode ent-

nommen werden können, kann der JProfiler nicht automatisch auf diese Ebene aggregieren. Die

Messungen wurden deshalb auf Package-Ebene aggregiert und anschließend die Packages ma-

nuell den Schichten zugeordnet. Einer Schicht wird hierbei nicht nur die Zeit zugeordnet, die in

ihren JCommSy Klassen verbracht wird, sondern auch die Zeit, die in aufgerufenen Fremdklassen

verbracht wird. Die Service-Schicht enthält beispielsweise die Zeit, die Hibernate benötigt. Die Er-

gebnisse sind in Tabelle 5.1 dargestellt. Mit 35 Prozent benötigt die Service-Schicht am längsten.

Dies beinhaltet die Datenbankzugriffe. Die Util-Schicht landet mit 34 Prozent an zweiter Stelle.

Die Präsentations- und die Items-Schicht bilden mit 20 bzw. 9 Prozent das Mittelfeld. Die Schicht

Domainvalue und Migration sind in dem derzeitigen Zustand fast bedeutungslos für die Ausfüh-

rungszeit des JCommSy. Eine Sonderrolle nimmt die Logik-Schicht ein, da sie zu diesem Zeit-

punkt noch keine Klasse enthielt. Insgesamt summieren sich die Ausführungszeiten der Schichten

zu 409 Sekunden, was bei 102 Anfragen ca. 4019 ms pro Anfrage ergibt. Dieser Wert ist nicht

direkt mit den Ergebnissen des JMeters zu vergleichen, da durch die vom Profiler durchgeführte

Instrumentierung und Protokollierung ein erheblicher Mehraufwand entsteht. Am JCommSy und

mit dem hier verwendeten Testsystem, kann der Profiler die Ausführung um Faktor 10 verlangsa-

men.

Die lange Ausführungszeit der Util-Schicht wird durch den PHPDeserializer verursacht. Eine

Optimierung und die entsprechenden Ergebnisse sind in Abschnitt 6.1.1 zu finden. Die Zeiten der

Präsentationsschicht werden durch die JSPs ausgemacht und nicht optimiert.

Einen großen Teil der Ausführungszeit verbringt das JCommSy im verwendeten Rahmenwerk Hi-

bernate. Das lässt sich damit begründen, dass Hibernate für den Datenbankzugriff verantwortlich

ist. Dies beinhaltet die Verwaltung von Datenbankverbindungen, das Erzeugen und Abschließen

von Transaktionen sowie die Zeit, die die Datenbank für das Bereitstellen der Daten braucht. Im

schlimmsten Fall muss die Datenbank die angeforderten Daten von der Festplatte lesen. Alles

das summiert sich zu der Zeit auf, die vom JProfiler Hibernate zugeordnet wird, welches aus der

Service-Schicht benutzt wird. Innerhalb der Service-Schicht wird der Großteil der Zeit durch die

Page 67: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.5 Performance des JCommSy 55

Schicht Speicher Anteil Anzahl an Allokationenin MB in Prozent in Tausend

service 368 MB 30,35 % 11016util 423 MB 34,88 % 4736presentation 381 MB 31,46 % 4498item 32 MB 2,66 % 1311domainvalue 2 MB 0,16 % 74migration 6 MB 0,49 % 91logic 0 KB 0 % 0Gesamt 1212 MB 100 % 21726

Tabelle 5.2: Speicherallokationen pro Schichten (Stand: 14. Oktober 2008)

Klasse FileServiceHibernate (siehe 6.1.4) und Zugriffe aus den IncludeTags verursacht (siehe

6.1.3).

5.5.2 Speicherverbrauch

In diesem Abschnitt wird der Speicherumsatz des JCommSy aus dem Blickwinkel der Schich-

tenarchitektur betrachtet. Speicherumsatz bezeichnet im Folgenden die Menge an Speicher, die

während des gemessenen Zeitraums für Objekterzeugung angefordert wurde. Ein Speicherumsatz

von 10 Megabyte (MB) bedeutet nicht, dass zu einem Zeitpunkt 10 MB Arbeitsspeicher benötigt

werden, sondern nur, dass in dem betrachteten Zeitraum insgesamt 10 MB Speicher angefordert

wurden.

Wie schon bei der Messung der Zeiten, hat der JProfiler keine Möglichkeit, die Daten auf die Ebe-

ne der Schichtung zu aggregieren. Es wird abermals auf Package-Ebene gemessen und von Hand

aggregiert.

Die Speicheranforderungen von gefilterten Klassen werden zu den aufrufenden Klassen hinzu-

gezählt, wie dies auch schon bei den Zeit-Messungen gemacht wurde. Ein Domainvalue erzeugt

beispielsweise ein Calendar-Objekt und ruft an dem Methoden auf, welche Strings und Dates

erzeugen. Gehört Calendar bereits zu den ausgefilterten Klassen, dann enthält Domainvalue trotz-

dem alle die Speicheranforderungen von Domainvalue, Calendar und auch String und Dates die

bei Domainvalues Benutzung von Calendar passiert sind. Die Ergebnisse der Messungen sind in

Tabelle 5.2 dargestellt.

Die meisten Objekterzeugungen und der größte Speicherumsatz passieren in den Util-, Service-

und Präsentationsschichten. Die Objekte der Präsentations- und Util-Schicht sind dabei durch-

schnittlich deutlich größer als die der Service-Schicht. Während die Service-Schicht z. B. die

fachlichen Items erzeugt, liegen in der Präsentationsschicht die JSP-Dateien, welche mit Strings

umgehen müssen. Diese werden benötigt, um die gewünschte HTML-Seite zusammenzustellen.

Innerhalb der Util-Schicht fordert der PHPDeserializer den Speicher an. Auch diese Klasse ar-

beitet auf Strings. String- und Char[]-Objekte machen insgesamt den größten Teil der Speicher-

belegung aus.

Page 68: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

56 Kapitel 5 Performance-Analyse

Die Objekte der Domainvalue-Schicht sind wertartig. Für detailliertere Informationen zu Wert-

Semantik wird auf MacLennan [Mac82] und Züllighoven [Z+98, S. 57 ff.] verwiesen. Wertartige

Objekte sind unveränderlich und können deshalb frei wiederverwendet werden (siehe [BGWA08]).

Daher müssen von und in dieser Schicht nur verhältnismäßig wenig Objekte erzeugt werden.

In der Verteilung der Speicherumsätze auf Klassenebene, fallen java.lang.StringBuilder, die

Spring-Klasse BeanFactoryUtils (siehe 2.4.6) und die Hibernate-Klasse Criteria heraus. Sie

verursachen mit 20, 17 bzw. 12 Prozent des insgesamt benötigten Speichers den größten Speicher-

umsatz. Die BeanFactoryUtils werden zum großen Teil aus der Service-Schicht aufgerufen. Ins-

besondere die Methode ServiceCreatorImpl.getService ruft diese auf. In Abschnitt 6.1.3 wird

eine Optimierung diesbezüglich durchgeführt und die Ergebnisse dargestellt.

Die Criteria-Klasse wird fast ausschließlich aus dem service.hibernate-Package verwendet.

Ein kleiner Anteil der Zugriffe erfolgt aus dem Migration-Package. Da diese Klasse des OR-

Mappers die Objekte zu den Daten der Datenbank erstellt, sind große Speicherumsätze zu erwar-

ten. Auffällig ist, dass der FileServiceHibernate alleine für 64 Prozent des Speicherumsatzes von

Criteria verantwortlich ist. Hier bietet sich Optimierungspotential (siehe 6.1.4).

Die weiteren Klassen mit signifikanten Speicherumsätzen sind die aus den JSPs generierten Klas-

sen. Diese werden der Präsentationsschicht zugeordnet. Alle zusammen benötigen sie mit 261 MB

ca. 21 Prozent des gesamten Speicherumsatzes.

Die erste JCommSy-Klasse, die in der Hotspots-Ansicht auftaucht, ist der PHPDeserializer. Die-

ser ist bereits bei der Messung der Ausführungszeit aufgefallen. Vier Prozent des Speicherumsat-

zes des JCommSy fordert die Klasse direkt an. Zusätzlich ist sie für 93 Prozent der Speicheranfor-

derungen des StringBuilders verantwortlich und damit ein weiterer Kandidat für Optimierungen

(siehe 6.1.1).

Zusammenfassend lässt sich feststellen, dass die Programmteile, die für großen Speicherumsatz

sorgen, die Ein- und Ausgaberahmenwerke sind. Servlets und JSPs für die Ausgabe per HTML

und Hibernate und Spring für die Erzeugung und das Einlesen der Objekte. Lediglich die Util-

Schicht fällt aus diesem erwarteten Muster heraus.

5.5.3 Auswirkungen von Ajax

Das JCommSy bietet die Möglichkeit, die Ajax-Technologie13 zu benutzen, um nicht die ganze

Seite bei jeder Anfrage neu zu übertragen, sondern nur die Bereiche, die sich verändert haben. Im

Fall vom JCommSy wird bei einem Wechsel zwischen den Detailseiten zweier Ankündigungen

z. B. der Navigationsbereich links nicht neu übertragen, da er sich nicht ändert. Dies hat für den

Benutzer den Vorteil, dass nicht mehr die ganze Seite neu dargestellt werden muss. Dies steigert

die wahrgenommene Performance (siehe 2.2).

Die Gegenüberstellung der Performance auf dem Server im Fall von aktiviertem und deaktivier-

tem Ajax kann nicht mit demselben Benchmark untersucht werden, wie die restliche Performance.

13Ajax steht für „Asynchronous JavaScript and XML“.

Page 69: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

5.5 Performance des JCommSy 57

Die Anfragen müssen spezielle Ajax-Informationen enthalten. Der dafür verwendete Benchmark

wird so definiert, das er 10 mal zwischen zwei Ankündigungsdetailseiten hin und her wechselt.

Er entspricht damit einem kleinen Makro-Benchmark, mit nur einem Use-Case als Grundlage.

Die Ergebnisse, die bei den Messungen herauskommen, lassen demnach nur Rückschlüsse darauf

zu, ob sich in diesem Testfall Performance-Vorteile ausmachen lassen oder nicht. Deshalb dürfen

gesparte Sekunden nicht absolut betrachtet werden oder als allgemeingültig für das JCommSy an-

genommen werden.

Die Antwortzeiten, wie sie mit dem JMeter gemessen werden, liegen fast gleich auf. Die mini-

malen Antwortzeiten sind ohne Ajax kürzer. Die durchschnittlichen Antwortzeiten sind allerdings

mit Ajax kürzer. Mit ca. 3 Prozent Unterschied, liegen die Abweichungen aber jeweils im Bereich

von maximal 20 Millisekunden. Die Messergebnisse können im Anhang in Abbildung A.2 und

A.3 angesehen werden.

Schaltet man Ajax ein, dann reduziert sich die Anzahl der Methodenaufrufe auf dem Server. Für

das tags-Package, welches alleine 33 Prozent der Ausführungszeit für diesen Benchmark aus-

macht, ergeben sich mit 8292 Aufrufen 1520 Aufrufe weniger, als ohne Ajax. Auf dem betrach-

teten System brachte das ein Geschwindigkeitsvorteil von 16 Prozent für dieses Package (13 Se-

kunden). Für service.impl werden 320 Aufrufe weniger registriert, also nur noch 1631. Dies

machte sich in 27 Sekunden kürzerer Ausführungszeit bemerkbar (30 Prozent). Die gesamte Aus-

führungszeit für den Benchmark lag bei 294 Sekunden ohne Ajax und bei 255 Sekunden mit Ajax.

Nicht beachtet wird hierbei, dass im Ajax-Fall nicht für jede Anfrage die Bilder und css-Dateien

neu geladen werden müssen. Dadurch spart man Anfragen und damit Zeit. Speichert ein Browser

diese Dateien lokal zwischen, entfällt auch dieser Vorteil.

Der maximale Speicherverbrauch liegt mit Ajax etwas höher, jedoch mit 29 zu 28 MB im Be-

reich der Schwankungen, die als nicht signifikant betrachtet werden können. Dies kann z. B. daran

liegen, dass das Garbage Collecting später ausgelöst wurde, weil die Anfragen schneller hinter-

einander ankamen.

Insgesamt lässt sich mit aktiviertem Ajax ein Performancevorteil für den Server ausmachen. Im

Verhältnis zu den am JCommSy durchgeführten Optimierungen ist er jedoch klein. Die vom Be-

nutzer wahrgenommene Performance der Anwendung steigt durch Ajax signifikant.

5.5.4 Bewertung

Die Analyse hat drei große Ansatzpunkte identifiziert, die optimiert werden können. Die entspre-

chenden Klassen sind jeweils sowohl bezüglich der Zeit, als auch bezüglich des Speichers heraus-

gefallen. Besonders auffällig ist die unerwartet hohe Bedeutung der Util-Schicht für die Perfor-

mance. Im nächsten Kapitel werden die Optimierungen detailliert vorgestellt und bewertet.

Die absoluten Zeiten, die bei der Messung mit dem Profiler herausgekommen sind, sind stark

durch den Profiler gekennzeichnet und dürfen dementsprechend nur vergleichend betrachtet wer-

den.

Page 70: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

58 Kapitel 5 Performance-Analyse

5.6 Zusammenfassung

Eine Performance-Analyse hat das Ziel die Performance eines Systems zu verbessern. Dafür wird

dies untersucht, Änderungen identifiziert, umgesetzt und deren Auswirkungen erfasst. Um das zu

leisten, werden eine abgeschlossene Testumgebung und Software-Werkzeuge benötigt. Mit JMe-

ter lassen sich HTTP-Anfragen generieren und wie ein Benchmark abspielen. Der JProfiler ist ein

Profiling-Werkzeug, das eingesetzt wird, um unterschiedliche Aspekte wie Ausführungszeit und

Speicherverbrauch zu messen. Für die Betrachtung der Performance lassen sich die drei Ebenen

Architektur, Klassen und Methode einnehmen. Auf Architekturebene ist es schwierig zu messen,

deshalb muss entsprechend aggregiert werden.

Die Performance Skala lässt sich in die fünf Kategorien I Java-Konstrukte, II Standardmethoden,

III Schleifen, IV Ein-/Ausgabe und V Algorithmen einteilen. Die einzelnen Bausteine aus denen

eine Anwendung besteht, wie z. B. ein Methodenaufruf oder ein Dateizugriff, können diesen Ka-

tegorien zugeordnet werden.

Das JCommSy verbringt über 70 Prozent seiner Ausführungszeit in den Schichten service und

util. Presentation beansprucht 20 Prozent. Alle drei zusammen sind für über 90 Prozent des

Speicherumsatzes verantwortlich. Die anderen Schichten sind, aus dem Performance-Blickwinkel

betrachtet, uninteressant. Die Klassen PHPDeserializer, IncludeTag und FileServiceHibernate

verbrauchen signifikant Ausführungszeit und sind Ansatzpunkte für Optimierungen.

Page 71: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

59

Kapitel 6

Ergebnisse der Refactorings undOptimierungen am JCommSy

Die beiden vorhergehenden Kapitel haben Schwachstellen des JCommSy bezüglich der Architek-

tur und der Performance aufgedeckt. In diesem Kapitel werden die daraus abgeleiteten Refacto-

rings und Optimierungen vorgestellt und deren Ergebnisse dargestellt. Abschließend werden die

Auswirkungen aller Optimierungen insgesamt erörtert und bewertet.

6.1 Durchgeführte Refactorings und Optimierungen

Im Folgenden werden die Refactorings und Optimierungen, die im Rahmen dieser Arbeit an dem

JCommSy durchgeführt wurden, vorgestellt und ihre Auswirkungen dargelegt. Die Optimierungen

„Deserialisierung“, „Spring Dependency Injection“ und „FileServiceHibernate erweitern“ werden

motiviert, deren Durchführung und die Resultate vorgestellt. Das Refactoring „Fachlogik extra-

hieren“ optimiert die Architektur des JCommSy. Dessen Auswirkungen auf die Performance und

die Architektur werden untersucht und die Ergebnisse dargestellt.

Die Auswahl der Optimierungen ist nach dem unter 2.2.5 beschriebenen Verfahren erfolgt. Es

wurde also jeweils zuerst die Optimierung durchgeführt, die am einfachsten schien. Die Reihen-

folge innerhalb dieses Kapitels entspricht der Reihenfolge in der die Änderungen am JCommSy

durchgeführt wurden. Da vor und nach jeder Optimierung gemessen wurde, beziehen die in den je-

weiligen Abschnitten angegebenen Messergebnisse die zuvor durchgeführten Optimierungen mit

ein. Angegebene absolute Zahlen, wie Ausführungszeiten oder Anzahl an Aufrufen, beziehen sich,

wenn nicht explizit anders angegeben, auf den für diese Arbeit entwickelten Benchmark (siehe

5.2.3).

6.1.1 Deserialisierung

Das Profiling zeigt, dass die util.PHPDeserializer-Klasse 35 Prozent der Zeit verbraucht. Sie ist

einer der ersten Kandidaten für Optimierung. Die Klassen PHPDeserializer und PHPSerializer

lagen ursprünglich im migration-Package. Ihre Namen legen nahe, dass sie PHP spezifisch sind.

Dies ist jedoch nur bedingt der Fall. Das PCommSy hat das Datenbankschema des JCommSy vor-

gegeben. Das Schema hat sich mit der Zeit weiterentwickelt, ist also gewachsen. Es sieht vor, dass

unterschiedliche Informationen von Items gemeinsam in einem String im Extras-Feld abgelegt

werden. Wird z. B. an einer Gruppe ein Bild gespeichert, so landet der Verweis auf dieses Bild im

Extras-Feld. Da unterschiedliche Informationen in dieses Feld gespeichert werden, wurde für die

Page 72: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

60 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

Speicherung innerhalb dieses Felds zunächst die Extensible Markup Language (XML) vorgese-

hen. Im Zuge der Weiterentwicklung wurde XML aufgegeben und stattdessen eine andere Form

der Speicherung gewählt, die bereits zum Serialisieren der Sitzungsinformationen benutzt wird.

Die beiden Klassen PHPSerializer und PHPDeserializer sind dafür verantwortlich, eine Objekt-

struktur in diese Form zu serialisieren, bzw. aus dem serialisierten String wieder eine entspre-

chende Objektstruktur aufzubauen. Sie sind also aufgrund des aufgeweichten Datenbankschemas

nötig. Solange es ein Extras-Feld gibt, werden die beiden Klassen benötigt.

Ist-ZustandDas Profiling ergibt, dass die Methoden PHPDeserializer.getToken und PHPDeserializer.check

24 bzw. 5 Prozent der Gesamtlaufzeit ausmachen. Beide sind mit 59 bzw. 2 Mikrosekunden (Ka-

tegorie II) nicht langsam verglichen mit anderen Methoden, sie werden jedoch vergleichsweise

häufig aufgerufen. Mit 1,3 Millionen bzw. 6 Millionen Aufrufen werden sie Faktor 10 bis 100

mal so oft aufgerufen, wie vergleichbare Methoden von Items (< 100 000 Aufrufe). Man kann im

JProfiler erkennen, dass getToken rekursiv wiederum von getToken aufgerufen wird. Die Rekur-

sion hat ihren Anfang in der Methode PHPDeserializer.deserialize, von wo aus sie gestartet

wird. Diese Methode wird wiederum von ExtrasItemImpl.getExtra eine Millionen mal aufgeru-

fen. ExtrasItemImpl ist eine Oberklasse vieler Items und bietet Zugriff auf die Informationen des

Extras-Felds.

Die Klasse ExtrasItemImpl ist so realisiert, dass sie sich intern den String, wie er im Extras-Feld

der Datenbank steht, in einer Exemplarvariable hält. Bei jeder Anfrage, die Informationen aus

dem Extras-Feld liefern soll, wird das Extras-Feld vom PHPDeserializer deserialisiert, so das ei-

ne Objektstruktur wie z. B. eine Map entsteht. Diese wird dann verwendet, um die gewünschten

Informationen zurückzugeben. Soll eine Veränderung am Extras-Feld gemacht werden, z. B. ei-

ne zusätzliche Information gespeichert werden, dann wird erst deserialisiert, die Veränderung am

Objekt gemacht und dieses danach wieder serialisiert. Diese Umsetzung ist konzeptionell einfach.

Darüber hinaus ermöglicht sie, dass Subklassen kein Wissen darüber benötigen, wie die Informa-

tionen in der Datenbank gespeichert werden.

VorgehenAls erster Schritt beim Optimieren muss ein Ansatzpunkt ausgewählt werden. Da die Methoden

von PHPDeserializer bereits kurze Ausführungszeiten hatten, wurde der Ansatz gewählt, die An-

zahl der Aufrufe zu verringern. Dafür wird ExtrasItemImpl genauer betrachtet.

Die erste Idee für eine Optimierung ist, die ExtrasItemImpl-Klasse so umzustellen, dass nur noch

genau dann serialisiert wird, wenn Hibernate mittels getExtras den String ausliest, der in die Da-

tenbank geschrieben wird. Analog wird nur noch genau dann deserialisiert, wenn Hibernate den

String mittels setExtras setzt. Dies hätte zur Folge, dass unabhängig von der Anzahl der Zugriffe

auf die Extras eines Items, immer genau einmal serialisiert und einmal deserialisiert wird.

ResultatDie Umstellung, dass ExtrasItemImpl immer beim Setzen und Abfragen zu (de)serialisieren, sorg-

te dafür, dass getToken nur noch 226 000 mal aufgerufen wurde und damit nur noch ein Prozent

Page 73: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.1 Durchgeführte Refactorings und Optimierungen 61

der Gesamtzeit des JCommSy brauchte. Trotzdem kam es zu einer Verschlechterung der Perfor-

mance. Das Setzen und Abfragen wird von Hibernate immer gemacht, auch dann, wenn gar nicht

(de)serialisiert hätte werden müssen, weil auf das Feld gar nicht zugegriffen wurde und/oder es

nicht verändert wurde. Verstärkt wird dies dadurch, dass Hibernate immer gleich mehrere Daten-

sätze auf einmal von der Datenbank abfragt und die Objekte erzeugt.

Als Folge dieses Optimierungsversuchs wird PHPSerializer zu einem Hotspot, der 53 Prozent

der Laufzeit verbraucht. Dessen unterschiedliche Serialisierungs-Methoden verbrauchen die Zeit

und führen zu einer Verschlechterung der Performance. Das legt nahe, dass die Klasse unterschei-

den können muss, zwischen Hibernate Zugriffen und der eigentlichen Benutzung des Felds. Des

Weiteren verdeutlicht dieses Szenario, wie wichtig es ist, jede vermeintliche Optimierung durch

Messungen zu bestätigen.

Vorgehen (2. Versuch)Hibernate benutzt die als privat deklarierten Methoden getExtras und setExtras. Diese Metho-

den tun nichts, außer den String aus der Exemplarvariable zu lesen, bzw. in diese zu schreiben.

Über die öffentlichen Methoden getExtra und setExtra können Informationen unter einem über-

gebenen Schlüssel im Extras-Feld abgelegt werden. Diese Methoden sorgen dafür, dass erst beim

ersten lesenden Zugriff deserialisiert wird und nur dann serialisiert wird, wenn ein schreibender

Zugriff stattgefunden hatte und Hibernate mittels getExtras den String für die Datenbank anfor-

dert. Die eigentliche Rekursion wurde nicht beschleunigt, sondern nur die Anzahl an Aufrufen

dieser Rekursion verringert.

ResultatDie Optimierung reduziert die Aufrufe an PHPDeserializer, so dass dieser nur noch 4 Prozent der

Laufzeit benötigt. Der Preis für die deutliche Verbesserung der Performance ist die Komplexität

der Klasse. Es wurden drei neue Exemplarvariablen eingeführt, in denen sich die Klasse merkt,

ob (De)Serialisierung benötigt wird. Die Methoden sind komplexer und damit fehleranfälliger

und schwieriger zu lesen. Die zusätzlichen Exemplarvariablen werden von allen Items geerbt. Der

Verdacht, dass dadurch der Speicherverbrauch der Anwendung steigt, lässt sich jedoch nicht be-

stätigen, sondern wird durch Messungen widerlegt. Es werden so signifikant viel weniger Objekte

erzeugt, dass die zusätzlichen Felder nicht ins Gewicht fallen. Die Util- und Item-Schichten for-

dern 81 bzw. 84 Prozent weniger Speicher an. Die 89 Prozent Geschwindigkeitsgewinn innerhalb

der Util-Schicht wurden also nicht gegen zusätzlichen Speicherverbrauch getauscht, sondern re-

duzierten diesen gleichzeitig.

Das Extras-Feld in der Datenbank sollte entfernt werden und entsprechende einzelne Felder, für

die enthaltenen Daten, angelegt werden. Dies ist jedoch nur in Absprache mit dem PCommSy

möglich, bzw. wenn das JCommSy alleine voll funktionsfähig ist.

6.1.2 Fachlogik extrahieren

Die Architektur des JCommSy sieht vor, dass die Präsentationsschicht gekapselt ist. Die Fachlogik

des JCommSy soll unabhängig von der Darstellung sein. Diese Fachlogik umfasst Funktionalitä-

Page 74: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

62 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

ten wie das Erzeugen neuer Ankündigungen, das Verknüpfen von Ankündigungen mit Materialien

oder das Editieren von Gruppen. Vor dem Refactoring war die Fachlogik zu großen Teilen in den

Ausstattern (siehe auch 4.4). Im Rahmen der Diplomarbeiten von Thiesen und Daricili ([Thi09]

und [Dar09]) wird die JSP-Oberfläche durch alternative Oberflächen ersetzt. Diese Oberflächen

verwenden die Fragmente und Ausstatter nicht. Da die Fachlogik jedoch in den Ausstattern ent-

halten ist, mussten sie vor diesem Refactoring zwingend verwendet werden, um die Fachlogik

wiederverwenden zu können. Durch das Refactoring wird die Fachlogik von den Ausstattern ent-

koppelt und damit wiederverwendbar. Die Fachlogik wird in eine eigene Schicht extrahiert.

...

forward

forward

TomcatMigrationFilter

CommsyServlet

FragmentServlet jsp Outfitter

checkUser/Session

request

response

isSupportedModuledoFilter

updateFragment

createParamBean

buildOutfitterTree(paramBean)

buildFragmentTree(paramBean)

doGet

updateItem ...

Abbildung 6.1: Sequenzdiagramm einer Anfrage vor dem Refactoring (Ausschnitt).Durch . . . ist der Zugriff auf die unteren Schichten angedeutet.Die Farben ordnen die Elemente den Schichten aus Abbildung 4.2 zu.

Ist-SituationIn Abbildung 6.1 ist der Ablauf einer Anfrage an das JCommSy in Form eines UML Sequenzdia-

gramms1 dargestellt. Zunächst entscheidet der MigrationFilter, ob die Anfrage vom JCommSy

oder vom PCommSy behandelt werden soll. Das daraufhin aufgerufene CommsyServlet überprüft,

ob ein Benutzer angemeldet ist und lädt die entsprechende Sitzung. Das anschließend aufgerufene

FragmentServlet hat die Aufgabe, den Bau des Ausstatter- und Fragmentbaums anzustoßen, wel-

1siehe [Sv06, S. 79 ff.]

Page 75: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.1 Durchgeführte Refactorings und Optimierungen 63

response

request

...

doFilter

forward

...

forward

forward

Tomcat MigrationFilter

CommsyServlet

FragmentServlet

jsp Outfitter

checkUser/Session

isSupportedModule

updateFragment

createParamBean

buildOutfitterTree(paramBean)

buildFragmentTree(paramBean)

doGet

updateItem

LogicServlet

Com-mand

...

execute

Abbildung 6.2: Sequenzdiagramm einer Anfrage nach dem Refactoring (Ausschnitt).Durch . . . ist der Zugriff auf die unteren Schichten angedeutet.Die Farben ordnen die Elemente den Schichten aus Abbildung 4.2 zu.

che die Daten für die Anzeige zusammenstellen und vorbereiten. Abschließend wird die Anfrage

an die JSPs weitergeleitet, in denen unter Verwendung der Fragmente die HTML-Seite generiert

wird.

In Abbildung 6.1 ist die Fachlogik exemplarisch durch die Methode updateItem dargestellt, wel-

che von den Ausstattern ausgeführt wird. Die Zugriffe auf die unteren Schichten sind in dem

Diagramm weggelassen, da sie sich durch das Refactoring nicht geändert haben.

VorgehenDie ursprüngliche Aufgabe der Ausstatter war das Befüllen der Fragmente mit den anzuzeigen-

den Daten. Im Laufe der Entwicklung des JCommSy haben die Ausstatter jedoch darüber hin-

ausgehende Aufgaben übernommen, wie beispielsweise das Speichern von Einträgen. Sie haben

damit einerseits die Aufgabe, Daten in das System hinein zu leiten und andererseits diese für die

Ausgabe aufzubereiten. Diese zwei grundsätzlich unterschiedlichen und voneinander unabhängi-

gen Funktionalitäten werden getrennt. Vor das FragmentServlet wird ein weiteres Servlet, das

LogicServlet, geschaltet (siehe Abbildung 6.2).

Das LogicServlet ist von Ausstattern und Fragmenten unabhängig. Es analysiert die eingehen-

den Daten und ruft das entsprechende Command auf. Ein Command stellt eine fachliche Aktivität dar

Page 76: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

64 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

Request Session

enthält Daten aus

ParamBean

liest

Command

verändert

Item

benutzt

Services

liest

Outfitter

benutzt

füllt

Fragment

liest

jsp

Abbildung 6.3: Schematischer Ablauf einer Anfrage an das JCommSyDie Farben ordnen die Elemente den Schichten aus Abbildung 4.2 zu.

und kapselt diese. Hat der Benutzer z. B. auf Bearbeiten einer Ankündigung geklickt, ist diese

Information in der am Server ankommenden HTTP-Anfrage enthalten. Die ParamBean macht die

Daten der Anfrage typisiert verfügbar. Aus dieser ParamBean extrahiert das LogicServlet die In-

formation, um das zuständige Command zu ermitteln. Dieses wird mittels Spring und Dependency

Injection erzeugt (siehe 2.4.6). Anschließend wird das Command ausgeführt und bearbeitet das

Item. Nachdem das Command ausgeführt wurde, kommt der Kontrollfluss zum FragmentServlet,

von wo die Ausstatter und Fragmente ausgeführt werden. Dieser Ablauf ist in Abbildung 6.2 als

Sequenzdiagramm dargestellt. Abbildung 6.3 stellt den Informationsfluss innerhalb des JCommSy

schematisch dar.

Die Bearbeiten-Seiten verhalten sich etwas anders, da die eingegebenen Informationen erhalten

bleiben müssen, ohne dass sie in die Items geschrieben werden. Am Beispiel einer Bearbeiten-

Seite einer Ankündigung wird dies verdeutlicht. Ein AnnouncementEditItemCommand wird erzeugt

und ausgeführt. Als Ein- und Ausgabeparameter erhält das Command die ParamBean und die Ser-

vices, wie alle anderen Commands auch. Im Fall eines Bearbeiten-Commands besteht dessen Auf-

gabe darin, aus der ParamBean die ID der Ankündigung zu lesen. Über die Services wird aus der

Datenbank das zugehörige AnnouncementItem geladen. Die Daten werden daraus gelesen und in

eine ItemEditBean geschrieben. Diese ItemEditBean wird als Ergebnis dieses Commands an die

ParamBean angefügt. Das LogicServlet leitet die Anfrage an das FragmentServlet weiter, wo der

zugehörige Ausstatter die ItemEditBean aus der ParamBean lädt und deren Informationen darstellt.

Dies ist schematisch und vereinfacht in Abbildung 6.4 zu sehen.

Page 77: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.1 Durchgeführte Refactorings und Optimierungen 65

Request Session

enthält Daten aus

ParamBean

liest

Command

benutzt

Item

benutzt

Services

fülltItemEditBean

liestEditOutfitter

füllt

Fragment

liest

Fragment

jsp

Abbildung 6.4: Schematischer Ablauf einer Anfrage für eine BearbeitenseiteDie Farben ordnen die Elemente den Schichten aus Abbildung 4.2 zu.

Ein Fragment und eine ItemEditBean sind beides Datenbehälter, sie haben jedoch unterschiedli-

che Aufgaben. Ein Fragment enthält genau die Informationen, die in einer JSP angezeigt werden

sollen. Fragmente werden bei jeder Anfrage neu befüllt, haben also eine Gültigkeitsdauer von ei-

ner Anfrage.

Im Gegensatz dazu, ist eine ItemEditBean über mehrere Anfragen hinweg gültig, solange bis

das Editieren abgebrochen oder gespeichert wird. Sie enthält die Informationen, die mit diesem

Editiervorgang verbunden sind. Beispielsweise wird die Beschreibung einer Ankündigung in der

ItemEditBean zwischengespeichert, bis der Benutzer das Speichern veranlasst. Die Informationen

in der ItemEditBean sind nicht auf eine JSP zugeschnitten, sondern auf den Vorgang „Editieren“.

Sie können von mehr als einem Ausstatter benutzt werden und so in mehr als ein Fragment (und

damit JSP) gelangen.

Zusammenfassend lassen sich damit folgende drei Arten von Beans im JCommSy ausmachen, die

jeweils ihren eigenen Aufgabenbereich haben:

Sitzung Die ParamBean enthält die Daten aus der Anfrage und der Antwort, sowie der Sitzung.

Editiervorgang Die ItemEditBean enthält die Daten eines fachlichen Vorgangs (z. B. Editieren),

wird von Commands befüllt und von einem oder mehreren Ausstattern lesend verwendet.

Darstellung Ein Fragment enthält die Daten für genau eine JSP und wird von genau einem Aus-

statter befüllt.

Vor dem Refactoring erlaubte die Architektur, dass die ItemEditBeans direkt aus den JSPs benutzt

werden. Der Zugriff auf die ItemEditBean ermöglicht das Sparen einer Indirektionsstufe. Die Da-

ten mussten nicht erst von den Ausstattern in die Fragmente geschrieben werden, sondern konnten

direkt aus den ItemEditBeans gelesen werden. Die Ausstatter hatten so nicht die Möglichkeit,

die genaue Form der Darstellung festzulegen, bzw. wenn sie es getan haben, dann haben sie es

Page 78: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

66 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

für alle Stellen festgelegt, in denen die Daten benutzt werden. Durch die Aufteilung ist es jetzt

z. B. möglich, das selbe Datumsobjekt an unterschiedlichen Stellen verschieden darzustellen. Die

zusätzliche Indirektionsstufe macht außerdem die Zuständigkeiten klarer deutlich. Die Ausstatter

werden wieder zu reinen Ausstattern und können als solche einfacher verstanden und weiterent-

wickelt werden. Die zusätzliche Indirektionsstufe betrifft die Performance-Kategorie I und wirkt

sich also im Bereich von Nanosekunden aus. Dies wird durch die Ausführung der JSP um drei

Kategorien überwogen.

Die ItemEditBean enthält alle Daten die während eines Editiervorgangs eingegeben werden. Es

ist nötig, diese an der Sitzung zu speichern, weil die CommSy-Benutzungsoberfläche vorsieht,

dass man aus einer Editieransicht auf eine andere Seite gelangt, von der aus man z. B. ande-

re Items dem aktuellen Item zuordnen kann. Der Editiervorgang wird dabei weder abgebrochen

noch abgeschlossen. Hat man seine Auswahl getätigt, kommt man wieder zurück zur Editieran-

sicht. Hier müssen die zuvor eingegebenen Werte zur Verfügung stehen. Sie werden dafür aus der

ItemEditBean gelesen. Sobald eine Editiersitzung durch Speichern, Abbrechen oder Löschen be-

endet wird, wird die ItemEditBean gelöscht.

Die Auswirkungen der zusätzlichen Schicht, sowie der zusätzlichen Indirektionsstufen und der

Verwendung des Command-Musters auf die Performance des JCommSy, werden im Folgenden

untersucht.

ResultatDas Refactoring hat folgende konzeptionelle, die Architektur betreffenden, Auswirkungen:

• Die Ausstatter sind übersichtlicher geworden. Die Ausstatter für Detail- und Indexseiten

arbeiten weiterhin nur auf den Items und befüllen mit deren Daten die Fragmente. Aus-

statter für Editierseiten arbeiten nur auf den ItemEditBeans und füllen mit deren Daten die

Fragmente. Zuvor mussten sie sowohl mit ItemEditBeans als auch mit Items umgehen.

• Die Ausstatter sind nur noch dafür da, die Fragmente zu befüllen. Sie haben nicht mehr

die Aufgabe die Items und die ItemEditBeans zu aktualisieren. Konzeptionell brauchen die

Ausstatter für Editierseiten die ParamBean nicht mehr, sondern nur noch die ItemEditBean.

Derzeit sieht die Schnittstelle aller Ausstatter aber die ParamBean als Parameter vor, so dass

dies nicht geändert wird.

• Die verändernde Logik ist komplett von der Darstellung entkoppelt. Das FragmentServlet,

welches die Ausstatter und Fragmente anstößt, ist dem LogicServlet nachgeschaltet und

das LogicServlet ist komplett unabhängig vom nachfolgenden FragmentServlet. Alterna-

tive Oberflächen können auf die Benutzung des FragmentServlets verzichten und haben

trotzdem die gesamte Logik zugreifbar. Dies war vorher nicht möglich, da die Logik in den

Ausstattern enthalten war.

• Die Fachlogik ist von der Oberflächentechnologie entkoppelt. Die Commands werden zwar

von dem LogicServlet ausgewählt und ausgeführt, haben jedoch selber keine Abhängig-

keiten von Komponenten des Servlet-Rahmenwerks. Sie benötigen lediglich die ParamBean

Page 79: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.1 Durchgeführte Refactorings und Optimierungen 67

und die Services. Auch der Auswahlmechanismus innerhalb des LogicServlets ist durch

die ParamBean von der Anfrage, und somit vom Servlet-Rahmenwerk, entkoppelt.

• Die Commands werden, wie die Services, mittels Spring und Dependency Injection erzeugt.

Gäbe es Test-Services, also Implementierungen der Services speziell für Tests, könnte diese

einfach für die Tests der Logik-Klassen benutzt werden. Solche Test-Services sind derzeit

nicht vorhanden, so dass relativ aufwendig Mock-Objekte für die Services erstellt werden

müssen. Dies macht den Quelltext der Logik-Tests lang und schwierig lesbar.

• Die Abhängigkeiten der JSPs von den ItemEditBeans sind gelöst. JSPs arbeiten ausschließ-

lich auf den Fragmenten.

Das Refactoring hat eine neue Schicht in die JCommSy-Architektur eingeführt. Es wurden neue

Klassen erstellt und diese zur Laufzeit ausgeführt. Der Umbau hat das nach außen sichtbare Ver-

halten nicht geändert und entspricht somit der Definition eines Refactorings [Fow99, S. 53]. Trotz-

dem könnten sich Auswirkungen auf die Performance ergeben. Die Messungen zeigen jedoch, dass

die Änderungen an der Gesamtperformance der Anwendung deutlich kleiner als die Schwankun-

gen der Messungen sind. Das Hinzufügen einer Schicht, die zusätzliche Benutzung des Command-

Musters (nach [GHJV95]), die Einführung mehrerer neuer Klassen und eines Servlets hat keine

Auswirkungen auf die Gesamtperformance.

Die zusätzliche Schicht und das Entwurfsmuster sind in Kategorie I einzuordnen. Die neuen Klas-

sen und die Servlets in Kategorie II. Diese sind, gegenüber den Kategorie IV Aspekten JSP und

Datenbankzugriff vernachlässigbar. Die Auswirkungen sind so klein, dass sie in den Schwankun-

gen innerhalb der Kategorie IV verschwinden.

Ein weiterer Punkt der verhindert, dass die Performance sich verschlechtert ist, dass der Ausstat-

terbaum seltener aufgebaut und ausgeführt wird. Dies passiert nur noch, wenn eine Seite ausge-

liefert werden soll. Gab es vorher eine Weiterleitung innerhalb des JCommSy, so mussten zuerst

die Ausstatter ausgeführt werden, bevor dies festgestellt werden konnte. Durch die sauberere Tren-

nung von Logik- und Darstellungsaspekten (also durch eine striktere Architektur) konnte unnötige

Berechnungen der Kategorie II und III gespart werden.

Die Logik-Schicht macht mit 0,57 Prozent einen vernachlässigbaren Anteil der Ausführungszeit

aus (siehe Tabelle 6.1 in Abschnitt 6.3.1). Die 0,57 Prozent werden durch die aus den Ausstattern

in die Logik-Schicht verschobenen Funktionalitäten ausgemacht.

6.1.3 Spring Dependency Injection

Das Profiling nach den zwei in den vorherigen Abschnitten durchgeführten Umbaumaßnahmen

ergibt, dass die Methode BeanFactoryUtils.beanOfType mit 37 Prozent einen großen Teil der

Laufzeit verursacht, wobei diese durch nur 5510 Aufrufe verbraucht wird. Die Klasse gehört nicht

zum JCommSy-Quelltext, sondern zum Spring-Rahmenwerk (siehe 2.4.6). In einer XML-Datei

spezifiziert das JCommSy, welche Klassen unter welchem Namen von Spring verwaltet werden.

Page 80: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

68 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

Spring ist dafür verantwortlich, ein Objekt der Klasse zu erzeugen und alle Abhängigkeiten die-

ser Klasse zu erfüllen. Die Klasse BeanFactoryUtils ist eine Hilfsklasse, die es ermöglicht ein

Objekt zu erhalten, dass einem bestimmten Typ genügt. Beispielsweise ist in der XML-Datei kon-

figuriert, dass es eine Klasse AnnouncementServiceHibernate gibt. Diese Klasse implementiert

das AnnouncementService-Interface. Benötigt ein Ausstatter einen AnnouncementService, kann er

einen solchen erhalten, ohne dass er dafür die Hibernate-spezifische Implementierungsklasse ken-

nen muss. Diese bleibt komplett im impl-Package der Service-Schicht gekapselt.

Im JCommSy wird dieser Spring Mechanismus nicht nur für die Services verwendet, sondern

auch zum Erzeugen der Ausstatter und Commands. Zusätzlich bietet er einen Zugriffspunkt auf

die CommsyProperties. Dieses Objekt enthält JCommSy-spezifische Einstellungen, wie z. B. die

URL2 unter der das JCommSy verfügbar ist.

Ist-Situation

Von den Aufrufen von beanOfType stammen 93 Prozent vom ServiceCreator, 6 Prozent vom

OutfitterCreator und weniger als ein Prozent vom CommandCreator. Wiederum über 85 Prozent

der Zugriffe auf den ServiceCreator passieren aus den Tag-Klassen, um die CommsyProperties

zu erhalten. Diese Funktionalität wird von den Tags benutzt um Links mit der richtigen URL zu-

sammen bauen zu können. Ungefähr 30 Prozent der gesamten Laufzeit wird dadurch verursacht,

dass der LinkTag die CommsyProperties abfragt.

Die Anzahl an Aufrufen von beanOfType ist mit 5510 nicht besonders groß, die Ausführungszeit

mit durchschnittlich 122 ms ist aber lang (Kategorie IV). Ähnlich lange durchschnittliche Aus-

führungszeiten sieht man bei Criteria.list, wo es aber unvermeidlich ist, da die Daten in der

Datenbank liegen und ein Zugriff darauf nötig ist.

Die Architektur des JCommSy sieht vor, dass ein ContextListener beim Start der Anwendung

Spring initialisiert. Im gleichen Schritt wird unter anderem die Datei commsy.properties gelesen

und ein CommsyProperties-Objekt erstellt. Dieses wird unter dem Namen „commsyProperties“

als Attribut am ServletContext gesetzt. Über den ServletContext kann auf die Einstellungen

von anderen Stellen aus zugegriffen werden.

Entgegen diesem Prinzip wird derzeit in jedem CommSyTag ein neuer ServiceCreator erzeugt,

dieser nach den CommsyProperties gefragt und diese anschließend benutzt. Das Erzeugen des

ServiceCreators erfordert das Einlesen der Konfigurationsdateien, deren Überprüfung auf Gül-

tigkeit und weitere Schritte. Mehrere Tags erweitern das CommSyTag, so dass es zu mehr als 3500

Aufrufen kommt.

Vorgehen

Die Tags wurden so angepasst, dass sie die CommsyProperties aus dem ServletContext benutzen.

Die Funktionalität wurde in eine gemeinsame Oberklasse extrahiert.

2Ein Uniform Resource Locator (URL) identifiziert und lokalisiert eine Ressource in einem Netzwerk.

Page 81: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.1 Durchgeführte Refactorings und Optimierungen 69

ResultatDurch die Benutzung des existierenden CommsyProperties-Objekts werden 3708 Aufrufe von

BeanFactoryUtils.beanOfType gespart. Dies bringt einen Geschwindigkeitszuwachs von 84 Pro-

zent für diese Methode. Damit reduziert sich die Gesamtzeit, die die Anwendung in dieser Metho-

de verbringt, von 37 Prozent auf 9 Prozent, die Anwendung hat sich um 28 Prozent beschleunigt.

Weiterhin muss es einmal einen Zugriff auf das Dateisystem geben und die Einstellungsdatei gela-

den werden. Für diesen einen Zugriff, wird weiterhin ein Kategorie IV-Aspekt vorhanden bleiben.

Für alle folgenden Zugriffe konnte jedoch durch die Optimierung der Aufwand auf Kategorie II

reduziert werden.

Der IncludeTag wurde ebenfalls so geändert, dass er das bereits existierende CommsyProperties-

Objekt verwendet. Vor den Umbaumaßnahmen war der IncludeTag indirekt für 266 MB Speicher-

Allokationen verantwortlich. Dies entspricht 35 Prozent des Gesamtspeicherumsatzes und liegt

vor dem des FileServiceHibernate mit 100 MB (siehe 6.1.4). Nach der Umbaumaßnahme sind

es nur noch 5 MB.

Diese Optimierung wäre nicht nötig gewesen, wenn klarer kommuniziert worden wäre, dass die

Architektur vorsieht, dass das vorhandene CommsyProperties-Objekt zu verwenden ist. Wäre die

Architektur so klar strukturiert, dass z. B. eine Regel genau vorgibt, wo die Zuständigkeit für

„Einstellungen laden“ liegen, wäre das Problem nicht aufgetreten. Alternativ könnte es eine Ver-

botsregel geben, die beschreibt, dass Klassen aus dem Tags-Package nicht auf Services zugreifen

dürfen.

Eine überprüfbare Regel gibt es nicht, dennoch hätte dieses Problem auch dadurch verhindert

werden können, dass die Vorstellungen über die Zuständigkeit (also die Architektur) besser kom-

muniziert worden wären. An dieser Situation sorgt eine sauberere und ausreichend kommunizierte

Architektur für bessere Performance. Am JCommSy ist gerade das Kommunizieren der Architek-

tur schwierig in ausreichender Güte umzusetzen. Das JCommSy wird durch Lehre-Projekte und

Diplomarbeiten weiterentwickelt. Daraus resultiert, dass halbjährlich das gesamte Entwicklerteam

wechselt und nur wenige Personen das Projekt die gesamte Zeit begleiten. Zusätzlich ist die Ar-

chitektur so komplex, dass eine umfassende Kommunikation und Einarbeitung in der gegebenen

Zeit nicht machbar ist. Deshalb sollte die Architektur möglichst gut durch Regeln überprüfbar

sein. Mit dem Sotographen ist es z. B. möglich festzustellen, dass ein Zugriff aus den Tags auf

die Services passiert. Mit einer Regel die dies beschreibt, könnte dies automatisiert überprüft wer-

den. Dafür müsste wiederum eine regelmäßige Überprüfung stattfinden und vorzugsweise in den

Entwicklungsprozess automatisiert integriert sein.

Neue Ist-SituationDie Performance hat sich deutlich verbessert, jedoch steckt weiterhin Optimierungspotential in der

Anzahl der Aufrufe von beanOfType. Der ServiceCreator generiert 1154 Aufrufe von beanOfType,

die sich alle auf Services beziehen. Diese Services sind zustandslos und die Objekte werden wie-

derverwendet, d. h. Spring liefert für zwei Anfragen nach dem AnnouncementService dieselbe Re-

ferenz zurück. Dennoch ist der Spring-Mechanismus langsam.

Page 82: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

70 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

VorgehenDer ServiceCreator wird so umgestellt, dass er in einer Map die Services zwischenspeichert,

die er bereits herausgegeben hat. Wird ein Service erneut angefragt, kann er ohne Spring aus

der Map geliefert werden. Voraussetzung dafür ist, dass die Aufrufe am selben ServiceCreator

passieren. Dafür wird der ContextListener so erweitert, dass er nicht bei jedem Aufruf einen

neuen ServiceCreator erzeugt, sondern für jeden Kontext nur genau einen.

ResultatDie Optimierung bringt einen weiteren Geschwindigkeitsvorteil von 5 Prozent, indem sie die An-

zahl der Aufrufe an beanOfType auf 648 reduziert. Durch diese Optimierung wird die Komplexität

erhöht. Falls die Services zukünftig einen Zustand haben sollten oder zur Laufzeit aus einem an-

deren Grund nicht mehr dasselbe Objekt wiederverwendet werden soll, stellt die Optimierung ein

zusätzliches Hindernis dar. Die Optimierung ist einfach wieder zu entfernen, aber es müsste manu-

ell gemacht werden und ist somit eine zusätzliche Fehlerquelle. Ohne diese Optimierung müsste

die Änderung nur in der entsprechenden XML-Datei von Spring gemacht werden. Die bessere

Performance erhöht hier also die Komplexität der Architektur, indem sie die zusätzliche Regel im-

pliziert, dass Services wiederverwendet werden können und es nicht mehr als ein Exemplar geben

können muss. Im Gegensatz zu der Optimierung bezüglich der Serialisierung (siehe 6.1.1) sind

hier mehrere Klassen und eine XML-Datei betroffen und sie bezieht sich auf zwei Schichten.

6.1.4 FileServiceHibernate erweitern

Das JCommSy verbringt 24 Prozent der Zeit in der Methode FileServiceHibernate.getFiles.

Deren Ausführungszeiten liegen mit durchschnittlich 37 ms in derselben Größenordnung wie an-

dere Service-Methoden, die auf die Datenbank zugreifen, jedoch wird diese Methode mit 1464

Aufrufen ca. 50 mal so oft aufgerufen. JProfiler bietet die Möglichkeit, sich Datenbankzugriffe

anzeigen zu lassen. Durch diese Methode werden 33 Prozent der Datenbankzeiten ausgemacht.

Die Methode bietet das größte Optimierungspotenzial.

Ist-SituationDer Aufrufstack, der vom JProfiler dargestellt wird, gibt Aufschluss darüber, dass die Klasse

AbstractIndexListOutfitter für die vielen Aufrufe verantwortlich ist. Dieser Ausstatter füllt

eine Liste von Zeilen für eine Index-Seite. Das passiert bei jedem Aufruf einer Index-Seite. Jede

Zeile repräsentiert ein Item. Für jedes Item soll die Information dargestellt werden, ob Dateien an

das Item angefügt sind oder nicht.

1 for (Item item : listOfItems) {

2 ...

3 indexlist.addRow(item.getItemID().toString(), ... ,

4 fileService.getFiles(item.getItemID()), ...);

5 ...

6 }

Quelltext 6.1: Benutzung des FileService durch den AbstractIndexListOutfitter

Page 83: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.1 Durchgeführte Refactorings und Optimierungen 71

Quelltext 6.1 stellt dar, dass der AbstractIndexListOutfitter während er über die Items iteriert,

für jedes Item den FileService nach einem Array von CommSyFiles fragt. Jeder dieser Aufrufe

resultiert in einer Datenbankanfrage.

Die Methode FileService.getFiles wird noch von anderen Klassen benutzt, wie beispielsweise

dem AbstractSaveItemCommand. Diese Klasse ist für das Speichern eines Items zuständig. Sie

behandelt genau ein Item und ruft die Methode dementsprechend selten auf.

VorgehenDer FileService wird um eine Methode erweitert, die es erlaubt, für eine Menge von Items, die

zugehörigen Listen von CommSyFiles zu erhalten. Die Methode hat die Signatur getFilesForIDs(

final Set<ItemID> itemIDs) und liefert ein Objekt vom Typ Map<ItemID, List<CommSyFile>>

zurück. Der Service hat die Möglichkeit, mit nur einer Datenbankanfrage alle CommSyFiles aus

der Datenbank zu laden. Anschließend werden diese in einer Map unter der zugehörigen ItemID

abgelegt.

Der Quelltext des Aufrufers ist in Quelltext 6.2 dargestellt.

1 // get all ids of this index−page2 final Set<ItemID> ids = new HashSet<ItemID>();

3 for (final Item item : listOfItems) {

4 ids.add(item.getItemID());

5 }

67 // get all linked files8 final Map<ItemID, List<CommSyFile>> linkedFiles = fileService.getFilesForIDs(ids);

910 // build rows11 for(Item item : listOfItems) {

12 ...

13 final CommSyFile[] linkedFilesArray = linkedFiles.get(item.getItemID()).toArray(

14 new CommSyFile[0]);

15 indexlist.addRow(item.getItemID(), ... , linkedFilesArray , ...);

16 }

Quelltext 6.2: Ausschnitt AbstractIndexListOutfitter nach der Optimierung

Der Zugriff auf den FileService ist aus der Schleife herausgezogen (Zeile 8). Er passiert genau

einmal und liefert eine Map. In der Schleife wird nur noch auf der Map gearbeitet (Zeile 13-15).

ResultatDie Optimierung sorgt dafür, dass die FileService.getFiles-Methode anstelle von 1464 mal nur

noch 40 mal aufgerufen wird. Die neu hinzugekommene Methode FileService.getFilesForIDs

wird 62 mal aufgerufen, genau einmal pro angezeigter Index-Seite. Das Resultat für das JComm-

Sy ist ein Geschwindigkeitsgewinn von 22 Prozent.

Der Zugriff auf die Datenbank ist unvermeidbar, eine Kategorie IV Performance also inhärent

in der Funktionalität enthalten. Vor der Optimierung war die Performance jedoch durch einen

Page 84: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

72 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

Algorithmus geprägt (Kategorie V), der den Zugriff deutlich öfter als nötig ausgeführt hat. Die

Optimierung hat also eine Verbesserung von Kategorie V nach IV bewirkt.

Diese Optimierung hat keine Komplexität zum JCommSy hinzugefügt, weder auf Architektur-

noch auf Klassenebene. Der FileService wurde um eine Methode erweitert, welche keine neue

Funktionalität liefert. Dies ist z. B. vergleichbar mit der addAll-Methode einer Liste. Die Schnitt-

stelle der Liste wird dadurch etwas breiter, teilweise einfacher zu benutzen und es ergeben sich

Vorteile bei der Performance. Dennoch ließe sich dieselbe Funktionalität auch ohne addAll errei-

chen. Gleiches gilt für den FileService.

Die aufrufende Klasse ist 10 Zeilen länger geworden, jedoch konzeptionell nicht schwieriger zu

verstehen. Die Funktionalität der getFiles-Methode lässt sich durch die neue Methode abbilden.

Die ursprüngliche Methode hätte also wegfallen können und alle Aufrufe entsprechend über die

neue Methode passieren können. Dann wäre die Schnittstelle nicht breiter geworden. Dies hätte

jedoch die Klassen, in denen prinzipiell nur die CommSyFiles von einem Item gebraucht werden,

unnötig komplizierter gemacht.

Es stellt sich die Frage, ob die Service-Schicht durch das Hinzufügen dieser Methode implizit von

der Präsentationsschicht abhängig gemacht wurde, bzw. zu sehr auf diese spezielle Oberflächen-

technologie zugeschnitten ist. Dies ist nicht der Fall: Das Benutzungsmodell des CommSy sieht

vor, dass die Übersichtsdarstellung Informationen über mehrere Items gleichzeitig anzeigt. Für

alle diese Items soll die Information, welche Dateien zu ihnen gehören, dargestellt werden. Die

neu hinzugekommene Methode entspricht also einer fachlichen Anforderung und ist nicht auf eine

spezielle Oberfläche zugeschnitten.

6.1.5 StringBuilder benutzen

In Java sind String-Objekte unveränderlich. Die Sprache gestattet Zeichenkettenkonkatenation per

Plus-Operator. Eine Konkatenation zweier Strings führt zu dem Kopieren beider und der Erzeu-

gung eines neuen. Dies sollte, insbesondere in Schleifen, vermieden werden (siehe [BGWA08]).

Die LinkTag-Klasse ist dafür verantwortlich, HTML-Links zusammenzubauen. Dafür werden, ab-

hängig von den Eingabeparametern, viele Strings aneinandergehängt.

VorgehenIm Laufe dieser Optimierung wurden die meisten Konkatenationen innerhalb der Klasse ent-

fernt und durch die Verwendung eines StringBuilders ersetzt. StringBuilder ist ein veränder-

barer Typ, der dafür optimiert ist, eine längere Zeichenkette durch das Aneinanderfügen mehrerer

Strings zu erstellen.

ResultatVor der Optimierung hatte LinkTag insgesamt einen Umsatz von 15 MB (ca. 200.000 Allokatio-

nen). Danach ist der Umsatz um ein Drittel zurückgegangen, so dass er nur noch 10 MB beträgt.

Der Anteil am insgesamt umgesetzten Speicher sinkt von zwei auf ein Prozent.

Die Optimierung hat auf Methodenebene stattgefunden und es sind weder andere Methoden, noch

Page 85: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.2 Auswirkungen unterschiedlicher JVM-Modi 73

andere Klassen von ihr betroffen. Durch die Verwendung des StringBuilders wurde der Quell-

text länger. Gleichzeitig kommuniziert er das was er tut besser. Die Quelltexte 6.3 und 6.4 zeigen

Ausschnitte, die die Unterschiede verdeutlichen.

1 String url = "";

2 url = url + RequestParameter.CONTEXT_ID.getName() + "=" + getContext();

3 if (_target != null) {

4 url = url + "#" + _target;

5 }

6 ...

7 pageContext.getOut().print(url);

Quelltext 6.3: Ausschnitt LinkTag mit String-Konkatenation

1 final StringBuilder url = new StringBuilder(40);

2 url.append(RequestParameter.CONTEXT_ID.getName()).append("=").append(getContext());

3 if (_target != null) {

4 url.append("#").append(_target);

5 }

6 ...

7 pageContext.getOut().print(url);

Quelltext 6.4: Ausschnitt LinkTag mit StringBuilder

Es ist in Java nicht üblich, dass mehrere Methodenaufrufe am selben Objekt hintereinander ge-

schrieben werden. Die meisten verändernden Methoden haben den Rückgabetyp void. Ein ty-

pisches Beispiel sind Setter-Methoden. Die append-Methode gibt jedoch das veränderte Objekt

zurück, so dass hier diese kompakte Schreibweise gewählt werden kann. Sie hat hier den Vorteil,

dass in einer Zeile url jeweils um einen zusammengehörigen Aspekt erweitert wird (siehe z. B.

Zeile 2 in Quelltext 6.4).

6.2 Auswirkungen unterschiedlicher JVM-Modi

Die Methode IndexList_jsp._jspService und vergleichbare Methoden in aus JSPs generierten

Klassen, sowie die Services, unterliegen bei ihren Ausführungszeiten stärkeren Schwankungen, da

sie besonders viel Ein- und Ausgabe zu leisten haben. Im Laufe der Messungen hat sich für diese

Klassen gezeigt, dass Schwankungen im Bereich von 100 Prozent nach oben oder unten möglich

sind (bei konstanter Anzahl an Aufrufen).

Im Folgenden wird die Performance des JCommSy in unterschiedlichen JVM-Ausführungsmodi

diskutiert. Grundlage für die Messungen ist die Version vom 2. Dezember 2008, die Ergebnisse

sollten jedoch auf andere JCommSy-Versionen übertragbar sein.

Die Java Virtual Machine kann im Client- oder im Server-Modus ausgeführt werden (siehe 2.2.8).

Zusätzlich kann zur Startzeit der JVM festgelegt werden, ob „Assertions“ angeschaltet sind oder

nicht. Dies entscheidet darüber, ob assert-Ausdrücke ausgewertet werden sollen oder nicht. Mit

assert bietet Java die Möglichkeit Bedingungen wie Invarianten in den Quelltext einzubauen, de-

ren Überprüfung zur Startzeit der Anwendung an- oder ausgeschaltet werden kann. Im JCommSy

Page 86: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

74 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

wird der assert-Befehl benutzt, um das Vertragsmodell [Mey92] umzusetzen, also insbesondere

Vorbedingungen und Nachbedingungen für Methoden zu formulieren und zu überprüfen.

Es werden folgende vier Ausführungsmodi gegenübergestellt:

Client Dies entspricht den Standardeinstellungen auf dem Testsystem und damit dem Modus, mit

dem alle anderen Profilings in dieser Arbeit durchgeführt wurden. Die JVM wird im Client-

Modus ausgeführt und die Assertions sind ausgeschaltet.

Client/Asserts Hier wurde das JCommSy mit angeschalteter Assertions-Überprüfung im Client-

Modus ausgeführt.

Server Diese Messung wurde mit der JVM im Server-Modus ausgeführt. Die Assertions waren

deaktiviert.

Server/Optimiert Die JVM wurde im Server-Modus gestartet. Zusätzlich wurde der JVM zusätz-

licher Speicher zur Verfügung gestellt und dafür gesorgt, dass die Methoden bereits beim

ersten Aufruf in nativen Code übersetzt werden.

Der Vergleich erhebt nicht den Anspruch allgemeingültig zu sein, er liefert jedoch für das JComm-

Sy folgende Ergebnisse. Es lässt sich feststellen, dass es für die Performance des JCommSy kei-

nen signifikanten Unterschied macht, ob die Assertions ein- oder ausgeschaltet sind. Während die

Schichten domainvalue und util ohne Assertions minimal schneller laufen, ist die Item-Schicht

mit eingeschalteten Assertions minimal schneller. Insgesamt ist das JCommSy mit ausgeschal-

teten Assertions zwei Prozent schneller, der Unterschied ist aber kleiner als die Schwankungen

innerhalb der Service-Schicht, so dass das Ergebnis kaum aussagekräftig ist.

Im Server-Modus ist die Anwendung weniger als 0,2 Prozent schneller als im Client-Modus. Dies

ist wiederum signifikant viel weniger als die Schwankungen der einzelnen Schichten. Für das

JCommSy macht es keinen Performance-Unterschied, ob die JVM im Server- oder im Client-

Modus läuft.

Das Erzwingen des Übersetzens in nativen Code hat das JCommSy um 16 Prozent verlangsamt.

Dies ist also keine Optimierung. Auch der zusätzliche Speicher hat die Performance nicht verbes-

sern können.

Für das JCommSy lässt sich insgesamt feststellen, dass die Performance stark durch Ein- und

Ausgabe geprägt ist (siehe 6.3.1). Die unterschiedlichen Ausführungsmodi der JVM können die

Performance nicht signifikant verändern. Für eine detaillierte Tabelle der Ergebnisse siehe Anhang

A.1.

6.3 Auswirkungen auf Performance und Architektur

Die Ergebnisse jeder einzelnen Optimierung wurden bereits in den zugehörigen Abschnitten dar-

gestellt. Im Folgenden werden die Auswirkungen der Gesamtheit der Änderungen auf das JComm-

Sy betrachtet. Es wird zunächst die Performance in den Fokus gerückt. Für die Ausführungszeit

Page 87: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.3 Auswirkungen auf Performance und Architektur 75

Schicht Vorher Nachher VerbesserungZeit Anteil Zeit Anteil

service 143.990 ms 35,13 % 39.498 ms 24,63 % 72,57 %util 141.000 ms 34,40 % 18.177 ms 11,34 % 87,11 %presentation 83.682 ms 20,41 % 82.388 ms 51,38 % 1,55 %item 35.798 ms 8,73 % 15.244 ms 9,51 % 57,42 %domainvalue 3.889 ms 0,95 % 2.534 ms 1,58 % 34,84 %migration 1.566 ms 0,38 % 1.587 ms 0,99 % -1,34 %logic 0 ms 0 % 912 ms 0,57 % undefiniertGesamt 409.925 ms 100 % 160.340 ms 100 % 60,89 %

Tabelle 6.1: Vergleich der Ausführungszeiten der Schichten (Stand: 19. Dezember 2008)

wird ein Vergleich zwischen dem nicht-optimierten und dem optimierten JCommSy erstellt. An-

schließend werden die Auswirkungen auf die Architektur zusammengefasst.

6.3.1 Performance

Die Performance des JCommSy hat sich durch die Optimierungen und Refactorings, die in die-

sem Kapitel beschrieben worden sind, verbessert. Tabelle 6.1 stellt gegenüber, wie sich die Aus-

führungszeiten der Schichten verändert haben. Am deutlichsten ist die Verbesserung in der Util-

Schicht mit 87 Prozent. Die Präsentationsschicht hat nur eine kleine Beschleunigung von 1,55

Prozent erfahren. Mehr als 81 der 83 Sekunden dieser Schicht werden durch die JSPs ausgemacht.

Diese haben sich kaum verändert. Das Übersetzen der JSPs in Servlets und wie man die JSPs bzw.

die resultierenden Servlets optimieren könnte, wird hier nicht behandelt.

Die Migrations-Schicht hat ihre Ausführungszeit leicht verschlechtert. Die Änderungen liegen im

Bereich von 20 ms. Die Ursache können Änderungen durch die Weiterentwicklung des JCommSy

sein oder z. B. in unterschiedlich lang dauernden Festplattenzugriffen begründet sein.

Bei der Logik-Schicht kann nicht von einer Verbesserung oder Verschlechterung der Performance

gesprochen werden, da sie vorher nicht existierte. Obwohl die Schicht noch neu ist, zeichnet sich

die Tendenz ab, dass sie im Bezug auf Performance nicht signifikant sein wird und das, obwohl sie

nicht optimiert ist, nachträglich eingebaut ist und zusätzliche Indirektionen durch Entwurfsmuster

enthält.

Durch die Optimierungen hat sich der Schwerpunkt der Schichten, in denen die Anwendung Zeit

verbringt, verlagert. Wie für eine Schicht mit Hilfsfunktionalität zu erwarten, nimmt die Util-

Schicht jetzt keinen so großen Stellenwert mehr ein. Dennoch ist ein Wert von 11 Prozent nicht we-

nig. Würde das Datenbankschema des JCommSy angepasst werden, so dass das (De)Serialisieren

des Extras-Felds entfallen könnte, würde die Util-Schicht von 18 auf weniger als 1 Sekunde Aus-

führungszeit fallen. Unter der vereinfachenden Annahme, dass die Datenbankanfrage selber durch

die zusätzlichen Spalten nicht langsamer wird, gilt folgendes: Hibernate könnte rechnerisch mehr

als 1.000 Felder an der ExtrasItemImpl-Klasse setzen, bevor dies mit der derzeitigen durchschnitt-

lichen Zeit, die durch die Rekursion des PHPDeserializers ausgelöst wird, gleichzieht. Die Re-

Page 88: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

76 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

kursion ist in Kategorie III eingeordnet, die Zugriffe auf die einzelnen Felder liegen in der Mitte

von I, es liegt also wenigstens ein Faktor von 1.000 dazwischen. In welchen Grenzen die vereinfa-

chende Annahme gilt, kann im Rahmen dieser Arbeit nicht geklärt werden. Die Menge an Daten

wird durch die Aufteilung geringer, da weniger redundante Formatierungsinformationen benötigt

werden. Andererseits wird die Datenbank-Tabelle breiter, was Auswirkungen hat. Die Anzahl der

Aspekte die im Extras-Feld gespeichert werden, liegt bei weniger als 100.

Die Präsentationsschicht und die Service-Schicht machen zusammen über 75 Prozent der Ausfüh-

rungszeit aus. Sie werden im Wesentlichen durch die Verwendung der Rahmenwerke Servlet und

Spring sowie Hibernate für die Datenbankzugriffe ausgemacht. Dadurch sperren sie sich direk-

ter Optimierungen. Insgesamt ist die Performance durch Ein- und Ausgabe geprägt. 24 Prozent

der Ausführungszeit wird in Hibernate-Klassen verbracht und 33 Prozent werden durch die JSPs

ausgemacht. Weniger als 14 Prozent werden in JCommSy-Klassen verbracht. Der Wert von 14

Prozent enthält den Mehraufwand durch das Profiling. Der Faktor, um den das Profiling die An-

wendung ausbremst, ist abhängig von den Methoden die untersucht werden. Abschnitt 5.5.1 legt

ein Faktor von ca. 10 nahe. Dieser Faktor ist in den anderen Prozentangaben für Hibernate-Klassen

und JSPs nicht enthalten, da diese vom Profiling ausgeschlossen waren.

Pro Anfrage werden durchschnittlich 14 Zugriffe auf die Datenbank ausgeführt, was in durch-

schnittlich 33 ms Datenbankzeit pro Anfrage resultiert. Die restlichen 320 ms, die Hibernate-

Klassen pro Anfrage benötigen, liefert Hibernate die Daten aus dem Cache bzw. benötigt Hiber-

nate zum Verwalten der Objekte.

Bis auf die Rekursion zum Deserialisieren des Extras-Felds, gibt es keine aufwendigen Algorith-

men im JCommSy. Deshalb sind Kategorie IV-Aspekte entscheidend für die Gesamtperformance

und die Kategorie I-Aspekte, wie zusätzliche Schichten, haben keine Auswirkungen.

Um bezüglich der Service-Schicht weiter zu optimieren, könnten weitere Services-Methoden ge-

bündelt werden. Das Profil der unterschiedlichen Services ist jedoch flach. Das bedeutet, es müsste

an vielen unterschiedlichen Stellen optimiert werden und jede Optimierung könnte nur wenig zur

Verbesserung der Gesamtperformance beitragen.

Insgesamt lässt sich mit 61 Prozent eine signifikante Verbesserung der Performance ausmachen.

6.3.2 Architektur

Die Architektur wurde durch das Extrahieren der Fachlogik verbessert. Dieses Refactoring hat

das Verhalten der Anwendung nicht verändert, sondern nur die Fachlogik klarer von der Darstel-

lung getrennt. Das erleichtert die Weiterentwicklung beider Komponenten, da die Ausstatter nur

noch eine Funktionalität haben. Insgesamt ist die Soll-Architektur, wie sie in Abbildung 4.2 dar-

gestellt wird, ausgereifter und präziser. Neben der Verbesserung der Soll-Architektur ist auch die

Ist-Architektur verbessert worden. Im derzeitigen Entwicklungsstand gibt es keine Architektur-

verletzung mehr, d. h. die Abbildung 4.2 stellt gleichzeitig auch die Ist-Architektur dar.

Zusätzlich zur verbesserten Architektur ist die Dokumentation der Architektur besser geworden.

Page 89: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

6.4 Zusammenfassung 77

Es liegt eine aktuelle Architekturbeschreibung vor und es gibt ein Modell der Architektur für den

Sotoarc. Damit kann die Architektur besser kommuniziert und überprüft werden.

6.4 Zusammenfassung

Die Analysen in den vorhergehenden Kapiteln haben mögliche Optimierungen identifiziert. Die

Optimierung bezüglich der Deserialisierung des Extras-Feld der Datenbank, hat gezeigt, dass der

erste Ansatz beim Optimieren nicht immer zielführend ist. Dadurch, dass die betroffene Klasse

um zusätzliche Logik erweitert wurde, kann das (De)Serialisieren auf das nötige Mindestmaß be-

grenzt werden. Dies verbessert die Performance und erhöht die Komplexität der Klasse.

Das Extrahieren der Fachlogik in eine eigene Schicht hat nicht zu einer Verschlechterung der Per-

formance geführt. Die Zuständigkeiten der Ausstatter haben sich durch die Umgestaltung deutlich

geschärft. Alternative Oberflächen können die Fachlogik des JCommSy nun wiederverwenden.

Die Verwendung des Spring-Mechanismus zur Erzeugung und Verwaltung von Objekten hat Aus-

wirkungen auf die Performance. Wiederholte Aufrufe zur Erzeugung eines CommsyProperties-

Objekts, resultieren in schlechter Performance. Die Architektur sieht vor, dass die Tags ein bereits

existierendes Objekt verwenden, statt ein neues zu erzeugen. Wäre dieser Architekturaspekt kla-

rer kommuniziert oder automatisiert überprüft worden, hätte die schlechte Performance verhindert

werden können.

Im JCommSy gibt es eine Datenbankanfrage, die innerhalb einer Schleife ausgeführt wird. Durch

das Erweitern des zugehörigen Services, können diese Datenbankanfragen gebündelt in einer An-

frage passieren. Dies verbessert die Performance der Anwendung.

Die Wahl des Ausführungsmodus der JVM bietet kein Potenzial zur Optimierung der Performance

des JCommSy. Weder das Aus- und Anschalten der Assertions, noch die Ausführung im Server-

Modus haben signifikante Auswirkungen auf die Performance.

Insgesamt ist die Architektur klarer strukturiert und einfacher zu kommunizieren. Die Performance

des JCommSy hat sich durch die Optimierungen stark verbessert. Die Ausführungszeit hat sich um

61 Prozent verringert.

Page 90: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

78 Kapitel 6 Ergebnisse der Refactorings und Optimierungen am JCommSy

Page 91: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

79

Kapitel 7

Allgemeine Schlussfolgerungen

In diesem Kapitel wird vom JCommSy abstrahiert und die gewonnenen Erkenntnisse auf allge-

meinerer Ebene dargestellt und bewertet. Es liegen nur Messergebnisse für ein System vor, so

dass nicht von einer repräsentativen Anzahl an Messungen gesprochen werden kann. Es wird be-

gründet, warum eine Abstraktion gerechtfertigt ist und deren Aussagekraft eingeschätzt.

Wenn im Folgenden die Formulierung „keine Performance-Auswirkungen“ verwendet wird, dann

bedeutet das, dass es keine für die Performance der Anwendung signifikanten Auswirkungen gibt.

Es kann minimale Auswirkungen geben, welche jedoch unterhalb normaler Abweichungen liegen,

die z. B. durch unterschiedlich lange Festplattenzugriffe entstehen.

7.1 Externe Bibliotheken

Es können unterschiedliche Bereiche innerhalb von Anwendungen ausgemacht werden, die Aus-

wirkungen auf die Performance und die Architektur haben, aber nicht von den Entwicklern des

Projekts geschrieben sind, sondern über eingebundenen Bibliotheken hinzukommen. Diese wer-

den in diesem Abschnitt vorgestellt.

7.1.1 Logging

Es besteht die Notwendigkeit zur Laufzeit Informationen über den Zustand einer Anwendung zu

erhalten. Gerade bei Web-Anwendungen, ist es für den Entwickler schwierig, im Fehlerfall an

zusätzliche Informationen zu kommen. Es bietet sich an, Logging-Rahmenwerke einzusetzen, um

derartige Informationen verfügbar zu machen. Sie bieten u. a. eine Abstufung in Log-Level wie

Warnung, Fehler oder Information. Damit ist es möglich, den Detaillierungsgrad einzustellen, wel-

che Informationen ausgegeben werden sollen.

Die Ausgabe der Informationen erfolgt in eine Datei oder wird über ein Netzwerk an einen an-

deren Rechner übertragen. In beiden Fällen sind dafür langsame Ausgabe-Operationen nötig.

Debug-Informationen können darum schnell zu einem Flaschenhals der Performance der Anwen-

dung werden. Die Log-Level sollten deshalb mit Bedacht gewählt werden, so dass der normale

Betrieb nicht durch unnötiges Logging gebremst wird. Die korrekte Verwendung des Loggers

ermöglicht es darüber hinaus für jede Klasse einzustellen, ob, und wenn ja, wie detailliert das

Logging für sie durchgeführt werden soll. Bereits während der Entwicklung sollten Richtlinien

festgelegt werden, wie das Logging zu benutzen ist. So ist es im Betrieb möglich, bei Bedarf

die Logging Funktionalität zu nutzen und andernfalls keine Performance-Nachteile zu erhalten.

Page 92: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

80 Kapitel 7 Allgemeine Schlussfolgerungen

Deaktiviertes Logging verursacht keine signifikante Performance-Verschlechterungen gegenüber

einem System, das keine Logging-Anweisungen im Quelltext enthält. Der zusätzlich Aufwand bei

deaktiviertem Logging liegt im niedrigen Bereich der Kategorie I, im Gegensatz zu Kategorie IV

bei aktiviertem Logging.

7.1.2 Rahmenwerke allgemein

Rahmenwerke werden eingesetzt, um softwaretechnischen Ansprüchen wie Wiederverwendbar-

keit und Austauschbarkeit zu genügen und bestimmte Strukturen oder Funktionalitäten nicht selbst

implementieren zu müssen. Ein Rahmenwerk wie Hibernate befreit die Entwickler davon, ihr Pro-

gramm für eine spezielle Datenbank zu schreiben. Wird auf einen OR-Mapper aufgesetzt, kann

die eigentliche Datenbank ausgetauscht werden, ohne dass die Anwendung geändert werden muss.

Die Kapselung, die ein OR-Mapper erreicht, geht so weit, dass der Entwickler unter Umständen

nicht mehr weiß, wann das Rahmenwerk Datenbankzugriffe durchführt.

Ein Rahmenwerk wie Spring stellt z. B. den Dependency Injection Mechanismus bereit (siehe

2.4.6). Es ist für die Verwaltung und Erzeugung von Objekten zuständig. Die Allgemeinheit des

Rahmenwerks sorgt gleichzeitig für zusätzliche Berechnungen und Überprüfungen. Beispielswei-

se müssen Aspekte abgeprüft werden, die in der betrachteten Anwendung niemals auftreten, aber

in anderen Anwendungen auftreten können. Hier kostet Flexibilität Performance.

Ob die Verwendung von Rahmenwerken die Performance einer Anwendung verbessert oder ver-

schlechtert, kann im Rahmen dieser Arbeit nicht beantwortet werden. Einerseits sind Performance-

Einbußen aufgrund der Generizität des Rahmenwerks zu erwarten, andererseits ist ein Rahmen-

werk potentiell besser auf Performance optimiert als eine Eigenentwicklung. Beispielsweise bietet

Hibernate Caching-Mechanismen und explizite Schnittstellen um Einfluss auf die Performance zu

nehmen.

Es lässt sich jedoch feststellen, dass die Verwendung von Rahmenwerken die Performance vor

dem Entwickler verschleiert. Die Untersuchung mit dem Profiler zeigte, dass es die Rahmenwer-

ke sind, in denen signifikant Zeit verbracht wird. Für den Entwickler steht der Quelltext dieser

Rahmenwerke im Allgemeinen nicht zur Verfügung, genausowenig wie die Möglichkeit, direkt

Einfluss auf das Rahmenwerk zu nehmen. Seine Möglichkeiten zu Optimieren begrenzen sich

darauf, was von den Entwicklern des Rahmenwerks vorgesehen ist. Ein Beispiel hierfür ist der

externe Cache von Hibernate.

Bezüglich der Architektur hat die Verwendung von Rahmenwerken sowohl positive als auch nega-

tive Aspekte. Durch die Rahmenwerke werden eine klarere Struktur und bestimmte Vorgehenswei-

sen vorgegeben. Das Spring-Rahmenwerk legt beispielsweise nahe, dass Objekte per Dependency

Injection und von Spring erzeugt werden, anstatt das der Entwickler sie selber erzeugt.

Andererseits kann die Komplexität der Architektur steigen und sie wird dadurch schwieriger zu

kommunizieren. Bestimmte Funktionalitäten der Anwendung werden vor dem Entwickler ver-

borgen und passieren scheinbar automatisch. Für Entwickler ist ein Rahmenwerk in der Regel

eine Black-Box, also ein geschlossenes Gebilde, von dem er nur das Äußere (also die Schnitt-

Page 93: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

7.2 Vorgehen beim Optimieren 81

stelle) kennt. Durch die falsche Benutzung eines Rahmenwerks kommen weitere Fehlerquellen

hinzu. Dies trifft umso mehr zu, je weniger ein Entwickler das Rahmenwerk kennt. Er hat nicht

die Möglichkeit, das was passiert direkt im Quelltext nachzuvollziehen, sondern muss die in der

Dokumentation beschriebenen allgemeinen Konzepte verstehen.

7.2 Vorgehen beim Optimieren

In diesem Abschnitt wird vorgestellt, was beim Optimieren beachtet werden muss und wie vorge-

gangen werden sollte. Zusätzlich wird die Wichtigkeit von Performance als Qualitätseigenschaft

dargestellt.

7.2.1 Optimierungen durch Messungen belegen

Bereits bei einfachen Anwendungen ist es schwierig, korrekte Aussagen über deren Performance

zu machen, bzw. diese zu verbessern, ohne dass dies durch Messungen untermauert wird. Bei

einer komplexen Web-Anwendung, die in einer Hochsprache wie Java geschrieben ist, die in ei-

ner virtuellen Maschine läuft und Rahmenwerke einsetzt, ist es noch deutlich schwieriger, das

Performance-Verhalten vorauszusagen. Deswegen ist es unvermeidbar, jede vermeintliche Opti-

mierung durch Messungen zu belegen. Dies gilt bereits für kleine Optimierungen, die nur eine

Klasse oder Methode betreffen.

7.2.2 In den hohen Kategorien zuerst optimieren

Großes Optimierungspotential liegt in den höheren Kategorien. Dort kann bereits die Optimierung

innerhalb einer Kategorie signifikante Auswirkungen haben (siehe 5.4.1). Gibt es anstelle von

zwei nur noch einen Datenbankzugriff, ist die Performance zwar besser geworden, jedoch immer

noch in der gleichen Kategorie einzuordnen.

Besonders in der Kategorie V haben Optimierungen bereits innerhalb der Kategorie schnell große

Auswirkungen. In Kategorie IV kann es sich besonders lohnen, daraufhin zu optimieren, die An-

zahl der Ein- und Ausgabe-Zugriffe zu verringern. So kann z. B. durch das Zwischenspeichern

des Inhalts einer Datei, die Performance von Kategorie IV nach III oder II verbessert werden.

In den Kategorien IV und V, sowie zum Teil auch in III, kann bereits während der Entwick-

lung der Performance-Aspekt im Fokus behalten werden. Andererseits sollten vermeintliche Opti-

mierungen in den niedrigen Kategorien nicht schon während der Entwicklung eingebaut werden.

Beispielsweise sollte vermieden werden, eine Variable vor einer Schleife zu deklarieren, um sie

im Schleifenkörper nur noch zuweisen zu müssen. Dies ist vermeintlich schneller, für die Per-

formance der Anwendung aber nicht signifikant. Die Änderung hat, wenn überhaupt, nur Aus-

wirkungen innerhalb von Kategorie I. Andererseits macht sie den Quelltext fehleranfälliger und

schwieriger zu verstehen, da die Variable einen größeren Gültigkeitsbereich hat, als nötig (siehe

[BGWA08]).

Page 94: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

82 Kapitel 7 Allgemeine Schlussfolgerungen

Donald Knuth hat bereits 1974 festgestellt, dass verfrühtes Optimieren Gefahren birgt:

„We should forget about small efficiencies, say about 97% of the time: premature

optimization is the root of all evil.“ [Knu74]

Dies schließt nicht aus, dass auch innerhalb von Kategorie I optimiert werden kann, allerdings darf

dies nur in Form einer disziplinierten Optimierung mit Messungen geschehen und nur dann, wenn

gezeigt ist, dass Optimierung nötig ist. Nur so kann verhindert werden, dass die Performance nicht

versehentlich verschlechtert oder unnötig Komplexität hinzugefügt wird.

7.2.3 Flaches Profil anstreben

Die Untersuchung hat gezeigt, dass es zunächst eindeutig war, welche Bereiche der Anwendung

für die Performance ausschlaggebend waren. Es gab wenige Methoden, die viel Leistung bean-

spruchten und viele Methoden, die wenig Leistung beanspruchten. Dieses „steile“ Performance-

Profil ist eine typische Ausgangslage (siehe 2.2.7) und ermöglicht gezielte Optimierung. Die ers-

ten Optimierungen bringen große Performance-Verbesserungen. Durch die Optimierungen wird

das Profil zunehmend flacher, d. h. es gibt nicht mehr wenige Methoden, die viel Rechenzeit be-

anspruchen, sondern viele Methoden, die wenig Rechenzeit beanspruchen. Es ist von Anwendung

zu Anwendung unterschiedlich, wann das Profil als flach bezeichnet wird und inwiefern es dann

immer noch einzelne langsame Methoden gibt, die nicht weiter optimiert werden können. Je fla-

cher das Profil wird, desto schwieriger wird es, weiter zu optimieren und desto kleiner werden die

Verbesserungen, die erreicht werden können. Liegen keine harten Anforderungen bezüglich der

Performance vor, sollte man bei einem flachen Profil aufhören weiter zu optimieren.

In der Regel sind die ersten Optimierungen bezüglich der zu investierenden Zeit, der hinzukom-

menden Komplexität und der erreichten Verbesserung lohnenswert. Auch für Anwendungen mit

nur schwachen Performance-Anforderungen, lohnt sich ein Profiling, weil sich bereits mit gerin-

gen Investitionen deutliche Verbesserungen erreichen lassen.

7.2.4 Performance ist wichtig

Die Performance ist eine wichtige Qualitätseigenschaft von Software (siehe 2.2.4), die nicht ver-

nachlässigt werden sollte. Durch die zunehmend leistungsfähigeren Computer, rückt dieser Aspekt

aus dem Fokus von Softwareentwicklern. Gerade in modernen Hochsprachen wie Java, ist die Per-

formance einfach und nicht-invasiv messbar. Dies sollte genutzt werden und Performance wieder

mehr in den Mittelpunkt gerückt werden. Es sollte das Ziel sein, das disziplinierte Performance-

Betrachtungen und Optimierungen zum Bestandteil des Entwicklungsprozesses werden. Das be-

deutet, dass die Entwickler den Quelltext weiterhin mit dem Fokus auf Korrektheit und Lesbarkeit

schreiben. In einem extra Schritt wird auf Grundlage von Messungen die Performance untersucht

und gegebenenfalls optimiert.

Page 95: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

7.3 Auswirkungen von Performance-Optimierungen auf die Architektur 83

7.3 Auswirkungen von Performance-Optimierungen auf dieArchitektur

Obwohl sich eine Performance-Optimierung zunächst auf den Quelltext auswirkt, kann sie auch

Auswirkungen auf die Architektur haben. In diesem Abschnitt werden diese Auswirkungen dar-

gestellt.

7.3.1 Optimierungen erhöhen die Komplexität

Wird ein Flaschenhals in einer Anwendung identifiziert und entsprechend optimiert, so hat dies

unmittelbar Auswirkungen auf den Quelltext. Teilweise beschränken sich die Änderungen auf ei-

ne Klasse oder eine Methode und haben damit nur auf kleiner Ebene Auswirkungen. Sie erhöhen

dann höchstens die Komplexität einer einzelnen Klasse. Die erhöhte Komplexität kann sich darin

zeigen, dass der Quelltext schwieriger und schlechter zu lesen ist. Dies verletzt die Anforderung

an den Quelltext, dass er das was er tut auch kommuniziert. Eine Klasse, die Ergebnisse über

mehrere Methodenaufrufe hinweg zwischenspeichert, kann schwieriger zu verstehen und weiter-

zuentwickeln sein. Ein einfacher aber langsamer Algorithmus kann durch einen schnelleren, kom-

plizierteren Algorithmus ersetzt werden.

Zum Teil sind mehrere Klassen unterschiedlicher Schichten und deren Zusammenspiel von einer

Optimierung betroffen. Ist das der Fall, kann die Optimierung die Komplexität auf Architektur-

ebene betreffen. Werden beispielsweise in einer Schicht Objekte zwischengespeichert und wie-

derverwendet, dann ist diese Information Teil der Architektur und muss kommuniziert werden. Es

hat Auswirkungen für benutzende Schichten, wenn sie Objekte nicht exklusiv erhalten, sondern

gemeinsam verwenden. Beispielsweise muss damit gerechnet werden, dass sich der Zustand eines

Objektes ändert und damit entsprechend umgegangen werden.

Würde mit einer Optimierung zusätzliche Komplexität in die Architektur gebracht werden, muss

besonders sorgfältig abgewogen werden, welcher Aspekt wichtiger ist.

Nicht alle Optimierungen erhöhen die Komplexität, zum Teil wird sie nicht einmal auf Klassen-

ebene erhöht. Eine Optimierung kann die Komplexität verringern. Am Beispiel des JCommSy

konnte jedoch keine Performance-Optimierung gefunden werden, deren direkte Auswirkung eine

Senkung der Komplexität war. Dies könnte z. B. erreicht werden, wenn überflüssige Generizität

entfernt wird. Agile Entwicklungsmethoden, wie z. B. Extreme Programming (siehe [BA04]), ver-

folgen den Ansatz, stets die einfachste Lösung zu wählen und keine Funktionalität auf Vorrat zu

entwickeln. Sie wirken damit der Notwendigkeit von derartigen Optimierungen entgegen.

Durch Optimierungen können Architekturverletzungen aufgedeckt werden, insbesondere wenn sie

in schlechter Performance resultieren. Die Optimierung bewirkt dann gleichzeitig die Beseitigung

einer Architekturverletzung (siehe auch 7.4.3), was indirekt die Komplexität der Anwendung re-

duzieren kann.

Page 96: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

84 Kapitel 7 Allgemeine Schlussfolgerungen

7.4 Auswirkungen von sauberer Architektur auf die Performance

Im vorherigen Abschnitt wurden die Auswirkungen von Optimierungen auf die Architektur dis-

kutiert. Im Folgenden wird die andere Richtung betrachtet. Es wird gezeigt, wie sich saubere

Architektur und die Einhaltung von softwaretechnischen Prinzipien auf Performance auswirkt.

7.4.1 Ausbau von Schichtung oder Einführung von Entwurfsmustern

Sowohl Architektur als auch die Verwendung von Entwurfsmustern resultiert in zusätzlichen In-

direktionen. Die Einführung eines Entwurfsmusters resultiert beispielsweise in zusätzlichen Ob-

jekterzeugungen und Methodenaufrufen (siehe auch 5.4).

Für eine existierende, komplexe Anwendung hat weder das Hinzufügen einer Schicht, noch die

Verwendung von zusätzlichen Entwurfsmustern Auswirkungen auf die Performance. Ein- und

Ausgabe-Operationen oder aufwendige Berechnungen benötigen im Verhältnis deutlich mehr Re-

chenleistung, so dass die zusätzlichen Indirektionen keine Auswirkungen haben (siehe Abbildung

5.3).

Indirektionen durch Architektur und Entwurfsmuster haben Auswirkungen im Bereich von Na-

nosekunden, also in Kategorie I (siehe 5.4.1). Bereits Standardfunktionalitäten, wie der Aufruf

von toString, liegen eine Kategorie darüber (II). Aufwendige Methoden, die z. B. Schleifen oder

Rekursionen enthalten, sind im Bereich von 100 Mikrosekunden (Kategorie III) zu finden. Ein-

und Ausgabe-Operationen wie Netzwerkkommunikation oder Dateizugriffe verursachen Zeiten in

Kategorie IV (Millisekunden). Deshalb gilt zusammenfassend: Für nicht triviale Anwendungen

haben Indirektionen durch Architekturen und Entwurfsmuster keine Auswirkungen auf die Per-

formance.

Falls die Performance einer Anwendung durch das Hinzufügen einer Schicht schlechter wird, dann

liegt das daran, dass die Funktionalität der Schicht, bezüglich der Performance, signifikant ist.

Wird eine aufwendige Berechnung aus einer Schicht in eine neue Schicht verschoben, dann kann

die neue Schicht einen signifikanten Teil der Performance ausmachen. Da vergleichbare Berech-

nungen allerdings in der anderen Schicht nicht mehr ausgeführt werden, wird dort entsprechend

eine Verbesserung der Performance festzustellen sein. Die Tatsache, dass eine Berechnung in eine

eigene Schicht verlegt wird, bzw. mit Entwurfsmustern realisiert ist, hat keine Auswirkungen auf

die Performance der Anwendung. Für die Performance ist es unerheblich, wo die aufwendigen Be-

rechnungen liegen. Die softwaretechnischen Vorteile, die durch Kapselung in eine eigene Schicht

entstehen, können also voll ausgenutzt werden.

In dieser Arbeit wurde eine bestehende Anwendung weiterentwickelt. Es wurde nicht untersucht,

ob die initiale Entscheidung über die Architektur der Anwendung Auswirkungen auf die Perfor-

mance hat. Die Ergebnisse legen jedoch den Schluss nahe, dass dies nur signifikant ist, solange die

Anwendung trivial ist. Sobald die Anwendung Kategorie IV oder V Aspekte enthält, verschiebt

die Performance sich so drastisch, dass Indirektionen durch Architektur keine Rolle mehr spielen.

Page 97: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

7.4 Auswirkungen von sauberer Architektur auf die Performance 85

7.4.2 Softwaretechnische Prinzipien

Das Geheimnisprinzip gibt vor, das der Zugriff auf die interne Datenstruktur unterbunden wird

[Z+98, S. 23]. Die Datenkapselung resultiert in Getter- und Setter-Methoden, anstatt von Direkt-

zugriffen auf die Variablen. Der Mehraufwand liegt in Kategorie I und ist nicht signifikant.

Die Umsetzung des Vertragsmodells erfordert das Überprüfen von Vor- und Nachbedingungen

[Mey92]. Die dafür nötigen Berechnungen sind in der Regel in Kategorie I einzuordnen. Ab-

schnitt 6.2 zeigt am Beispiel des JCommSy, wie gering die Auswirkungen sind.

Klassen sollen eine hohe Kohäsion haben und möglichst lose mit anderen Klassen gekoppelt sein

[Z+98, S. 43]. Dies bedeutet, dass jede Einheit eine abgeschlossene logische Aufgabe hat. Auch

das sorgt für zusätzliche Indirektionen, z. B. wenn eine bestimmte Teilaufgabe von einer anderen

Klassen erfüllt wird. Wiederum sind diese Aspekte in der Kategorie I einzuordnen.

Entwurfsmuster sind bewährte Lösungs-Schablonen und die softwaretechnische Prinzipien beach-

ten [GHJV95]. Ihre Auswirkungen auf die Performance sind in die Kategorie I einzuordnen (siehe

7.4.1). Sie, genauso wie die Prinzipien, sollten nicht aus Performance-Gründen missachtet wer-

den. Wird festgestellt, dass die Performance nicht ausreichend ist und optimiert werden muss,

erlaubt die hohe Kohäsion einer Klasse, das gezielt und einzelne Klassen betreffend optimiert

werden kann. Das Geheimnisprinzip ermöglicht es, eine Klasse zu optimieren, indem z. B. intern

eine andere Struktur gewählt wird. Wäre diese von außen sichtbar, könnte sie nur dann optimiert

werden, wenn alle benutzenden Klassen angepasst würden. In einer komplexen Anwendung mit

Kategorie IV oder V-Aspekten, verschlechtert der Einsatz von softwaretechnischen Prinzipien die

Performance nicht. Ihre softwaretechnischen Vorteile, zusammen mit den daraus resultierenden

besseren Möglichkeiten zu optimieren, rechtfertigen ihre Einhaltung.

7.4.3 Performance durch Einhaltung der Architektur

Eine der Aufgaben einer Architektur ist es, Zuständigkeiten festzulegen. Wenn das nicht ausrei-

chend passiert, kann eine Verschlechterung der Performance die Folge sein. Beispielsweise können

teure Methoden öfter als nötig ausgeführt werden, wenn den Entwicklern nicht bekannt ist, dass

sie bereits ausgeführt wurden und deren Ergebnisse vorliegen. Legt die Architektur Zuständigkei-

ten fest, kann dies positive Auswirkungen auf die Performance haben. Eine Voraussetzung dafür

ist, dass die Architektur ausreichend kommuniziert wird. Weiß ein Entwickler nicht, dass eine an-

dere Komponente für etwas zuständig ist, wird er diese nicht benutzen. Gibt es zusätzlich keine

ausreichende Überprüfung der Architektur, dann wird nicht aufgedeckt, dass eine Architekturver-

letzung vorliegt und die Verschlechterung der Performance nicht verhindert.

Die Architektur kann die korrekte Verwendung von Rahmenwerken fordern und fördern. Sieht die

Architektur vor, dass die Datenbankzugriffe durch eine Service-Schicht gekapselt sind, gibt es nur

noch sie als zentrale Stelle, in der die korrekte Benutzung des Rahmenwerks sichergestellt sein

muss. Das führt dazu, dass eine Reihe von Performance-Konzepten automatisch Einzug in die

Anwendung erhalten. Der Auf- und Abbau einer Datenbankverbindung ist in Kategorie IV und

Page 98: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

86 Kapitel 7 Allgemeine Schlussfolgerungen

damit langsam. Durch die Kapselung der Datenbankzugriffe in eine Schicht und die Verwendung

von Hibernate muss sich die Anwendung beispielsweise nicht darum kümmern, dass Datenbank-

verbindungen bereitgehalten und wiederverwendet werden (siehe [BHRS07, S. 96 ff.]). Hibernate

übernimmt das und sorgt damit für eine Optimierung der Anwendung.

Eine klare Architektur, die kommuniziert und deren Einhaltung überprüft wird, hat positive Aus-

wirkungen auf die Performance einer Anwendung.

7.5 Datenbanken

Der Zugriff auf eine Datenbank ist verhältnismäßig langsam (Kategorie IV). Zum einen muss

eine Kommunikation zwischen unterschiedlichen Prozessen stattfinden, zum anderen muss die

Datenbank potentiell Ein-/Ausgabe-Operationen durchführen. Noch verstärkt wird das, wenn die

Datenbank auf einem anderen Rechner läuft und so Netzwerklatenzen hinzukommen. Der Zugriff

auf eine Datenbank ist somit eine performance-relevante Operation. In diesem Abschnitt werden

Ergebnisse vorgestellt, die den Zugriff auf die Datenbank betreffen.

7.5.1 Zugriffe bündeln

Die Untersuchungen haben gezeigt, dass durch das Bündeln von Datenbankzugriffen die Perfor-

mance verbessert werden kann. Es kann sinnvoll sein, statt in einer Schleife jeweils eine Informa-

tion aus der Datenbank zu holen, bereits vor der Schleife alle benötigten Informationen in einem

Datenbankzugriff zu holen. Wenn die Datenbankzugriffe durch eine Service-Schicht gekapselt

sind, dann müssen die Services entsprechendes leisten. Bieten sie keine Schnittstelle an, um ein

Bündel von Informationen auf einmal abzurufen, ist der Entwickler gezwungen, iterativ für alle

Informationen einen Aufruf an den Services zu machen. Die Performance einer Anwendung lässt

sich also steigern, wenn die Schnittstelle der Service-Schicht an die Art der Anfragen angepasst

wird. Dadurch wird die Service-Schicht um ein Stück anwendungsspezifische Logik erweitert,

geht also über eine einfache CRUD-Schnittstelle hinaus (siehe 4.4.1). Inwiefern es erlaubt und

gewünscht ist, dass die Service-Schicht diese Logik enthält, ist eine Architekturfrage.

Falls von vornherein klar ist, dass die Informationen immer als Bündel abgerufen werden, kann die

Methode bereits von Anfang an so entworfen werden, dass sie dieses Bündel zurückgibt. Andern-

falls sollte der Service erst dann um solche Methoden erweitert werden, wenn Profilings gezeigt

haben, dass bestimmte Informationen häufig unmittelbar nacheinander abgerufen werden und dies

in der derzeitigen Situation einen Flaschenhals darstellt.

Das Anpassen der Schnittstelle kann auf zwei Arten umgesetzt werden. Die Schnittstelle kann um

eine Methode erweitert werden oder es kann eine existierende Methode so angepasst werden, dass

sie das Bündel an Informationen liefert. Ersteres bietet sich an, wenn es auch Zugriffe gibt, bei

denen nur einzelne Informationen erfragt werden. Zweiteres bietet sich an, wenn die Informatio-

nen immer gemeinsam benötigt werden. Der Entwickler hat dann nicht mehr die Möglichkeit, den

Service aus Performance-Sicht falsch zu benutzen.

Page 99: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

7.5 Datenbanken 87

7.5.2 OR-Mapper

Datenbankanfragen liegen in Kategorie IV. Zu einer Datenbankanfrage gehört die Kommunikati-

on mit der Datenbank und das Abarbeiten der Anfrage in der Datenbank. Auf Anwendungsseite

wird dafür zunächst eine SQL-Anweisung erzeugt und nachdem das Ergebnis der Datenbankan-

frage vorliegt, dieses wieder in entsprechende Objekte verpackt, die Teil der Anwendungslogik

sind. Der zeitaufwendige Aspekt ist die Kommunikation. Abhängig von der Anfrage und ob die

Daten bereits im Hauptspeicher sind, kann auch die Bearbeitung innerhalb der Datenbank zeitauf-

wendig sein. Das Befüllen der Objekte mit den erhaltenen Daten ist in der Regel in Kategorie I

einzuordnen.

Wird in einer Anwendung ein OR-Mapper, wie Hibernate, eingesetzt, dann passiert das Generie-

ren der SQL-Anweisung und das abschließende Übertragen der Ergebnisse in die Objekte automa-

tisch. Zusätzlich werden einige Verwaltungsaufgaben anfallen, wie z. B. die Registrierung eines

Objektes im Cache. Diese Verwaltungsaufgaben sind II oder III-Aspekte und von den Entwicklern

des OR-Mappers auf Performance optimiert. Auch beim Einsatz eines OR-Mappers bleibt die ei-

gentliche Anfrage an die Datenbank der für die Performance ausschlaggebende Teil. Dadurch dass

ein OR-Mapper Anfragen z. B. durch Caching spart oder speziell für eine Datenbank optimiert,

kann die Performance gesteigert werden.

Für die Architektur bedeutet der Einsatz eines OR-Mappers, dass die Entwickler von den Eigenhei-

ten der Datenbank befreit werden. Es fällt in den Aufgabenbereich von Hibernate, in den speziellen

SQL-Dialekt der jeweiligen Datenbank zu übersetzen. Der Entwickler kann seine Anfragen über

eine objektorientierte Programmierschnittstelle formulieren (siehe auch 2.4.5). Der Zugriff auf die

Datenbank wird durch den OR-Mapper gekapselt und die Datenbank dadurch austauschbar.

7.5.3 Datenbankschema

Ein zu schwach strukturiertes Datenbankschema kann die Performance einer Anwendung negativ

beeinflussen. Das Datenbankschema der untersuchten Anwendung sieht eine Spalte vor, in der

zusätzliche Informationen in Textform gespeichert werden. Da dieses Feld für unterschiedliche

Informationen genutzt wird, muss der Inhalt von einem Parser in die einzelnen Informationen zer-

legt werden. Dieser Vorgang verschlechtert die Performance der Anwendung.

Eine Anpassung des Schemas derart, dass für jede Information eine eigene Spalte oder Tabelle

im Schema vorgesehen wäre, würde das Parsen überflüssig machen und dadurch die Performance

verbessern. Des Weiteren würde die Datenbank weniger redundante Informationen enthalten, wie

sie beispielsweise vom Parser benötigt werden, um die Informationen trennen zu können.

Die Auswirkungen eines saubereren Datenbankschemas auf die Datenbank selber und damit ein-

hergehende Performance-Verbesserungen oder -Verschlechterungen liegen aber nicht im Fokus

dieser Arbeit.

Page 100: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

88 Kapitel 7 Allgemeine Schlussfolgerungen

7.6 Zusammenfassung

Die Ergebnisse der Optimierungen, sowohl bezüglich der Performance, als auch hinsichtlich der

Architektur, werden in diesem Kapitel vom JCommSy abstrahiert.

Die Verwendung von Rahmenwerken kann positive und negative Auswirkungen auf die Perfor-

mance einer Anwendung haben. Rahmenwerke kapseln für die Performance relevante Aspekte.

Dadurch wird es für Entwickler schwieriger die Performance zu betrachten und zu optimieren,

wenn dies nicht explizit durch das Rahmenwerk unterstützt wird.

Beim Optimieren sollte stets abgewogen werden, ob weitere Optimierungen nötig sind. Ist das

Performance-Profil bereits flach, muss viel Aufwand für wenig zusätzliche Performance investiert

werden. Gute Performance kann die Benutzbarkeit einer Anwendung erhöhen und sollte ein Ziel

bei Softwareentwicklung sein.

Performance und Architektur sind nicht unabhängig voneinander. Die Komplexität der Architek-

tur kann durch Performance-Optimierungen erhöht werden. Andererseits können Optimierungen

Architekturverletzungen aufdecken und dadurch helfen die Architektur zu verbessern. Legt die

Architektur die Zuständigkeiten klar fest, kann dies Performance-Probleme verhindern, wie sie

z. B. durch Doppelberechnung oder falsche Benutzung von Rahmenwerken entstehen können.

Komplexe Architekturen und die Verwendung von Entwurfsmustern resultieren in zusätzlichen In-

direktionen. Diese haben auf die Gesamtperformance einer nicht trivialen Anwendung keine Aus-

wirkungen. Die Performance wird in solchen Anwendungen maßgeblich durch Ein- und Ausgabe-

Operationen oder aufwendige Berechnungen bestimmt. Deren Ausführungszeiten liegen mehrere

Kategorien über der, der Indirektionen.

Der Zugriff auf Datenbanken ist vergleichsweise langsam und hat Auswirkungen auf die Per-

formance. Durch das Bündeln von Datenbankanfragen zu einer Anfrage, kann die Performance

gesteigert werden. Wird das Datenbankschema aufgeweicht, so dass einzelne Felder unterschiedli-

che Informationen enthalten, kann dies aufwendiges Auseinanderrechnen der Informationen nötig

machen.

Page 101: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

89

Kapitel 8

Schlussbemerkungen

In diesem Kapitel werden die wesentlichen Punkte dieser Arbeit zusammengefasst und die Arbeit

abgeschlossen. Im Ausblick werden offen gebliebene Aspekte und Fragen beschrieben und somit

mögliche Ansatzpunkte für zukünftige Arbeiten gegeben.

8.1 Fazit

Das JCommSy konnte im Laufe dieser Arbeit, sowohl bezüglich der Architektur, als auch der

Performance, verbessert werden. Durch die durchgeführten Refactorings ist die Architektur klarer

geworden. Die Zuständigkeiten sind deutlicher und die Entkopplung der Darstellungslogik von

der Fachlogik vorangetrieben worden. Durch die Optimierungen konnte die Performance für die

untersuchten Testfälle um ca. 61 Prozent gesteigert werden. Die meisten der Optimierungen waren

auf kleiner Ebene und benötigten lediglich lokale Änderungen. Einige hatten Auswirkungen auf

die Architektur, sie haben diese jedoch nicht verschlechtert und keine Verletzungen hinzugefügt.

Die Analysen haben gezeigt, dass bei einer Web-Anwendung eine ausgeprägte Architektur und

die Performance nicht im Widerspruch stehen, sondern einander ergänzen und sowohl positive als

auch negative Auswirkungen aufeinander haben. Die Performance-Skala lässt sich in Kategorien

unterteilen. Indirektionen liegen in Kategorie I, während Datenbank- und Festplattenzugriffe in

IV liegen. Die durch eine ausgeprägte Architektur oder durch den Einsatz von Entwurfsmustern

entstehenden Indirektionen sind für die Gesamtperformance einer Web-Anwendung ohne Bedeu-

tung. Sie fallen neben den Kategorie IV und V-Aspekten nicht ins Gewicht.

Die Architektur wirkt in anderen Bereichen auf die Performance ein. Sie legt Zuständigkeiten fest

und strukturiert die Anwendung, so dass aufwendige Mehrfachberechnungen vermieden werden

können und die korrekte Benutzung von Rahmenwerken sichergestellt werden kann. Performance-

Optimierungen wirken auf den Quelltext der Anwendung meist in Form von Erhöhung der Kom-

plexität, wobei dies zum Teil auch die Architekturebene betrifft.

Ähnlich wie bei der Analyse der Architektur braucht man auch für die Betrachtung von Perfor-

mance Software-Werkzeuge. Mit diesen ist es möglich, die Performance einer Anwendung zu un-

tersuchen und Schwachstellen zu identifizieren. Zunächst können diese Schwachstellen, wenn sie

einmal identifiziert worden sind, relativ einfach und mit großen Performance-Vorteilen optimiert

werden. Mit zunehmender Anzahl an durchgeführten Optimierungen, wird das Kosten-Nutzen-

Verhältnis jedoch schlechter.

Gerade weil die ersten Optimierungen günstig sind, sollten Performance-Analysen zum Entwick-

lungsprozess dazu gehören. Performance ist eine wichtige Qualitätseigenschaft von Software und

Page 102: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

90 Kapitel 8 Schlussbemerkungen

sollte wieder mehr in den Fokus gerückt werden. Kleine, undiszipliniert durchgeführte Optimie-

rungen während des Programmierens bleiben allerdings weiterhin die „Wurzel allen Übels“ (siehe

7.2.2). Die Performance einer komplexen Anwendung kann kaum vorhergesagt werden, so dass

die Optimierungen immer durch Messungen zunächst gerechtfertigt und danach belegt werden

müssen.

8.2 Ausblick

Für die unterschiedlichen Erkenntnisse dieser Arbeit, wurde in unterschiedlichen Bereichen gear-

beitet. Nicht alle konnten dabei in gleichem Umfang bearbeitet werden. Das betrifft besonders den

Begriff Performance und dessen zahlreiche Ausprägungen. Auch bezüglich Architektur wurde nur

ein Ausschnitt bearbeitet. In diesem Ausblick werden deshalb offene Fragen und Ansatzpunkte für

zukünftige Arbeiten vorgestellt.

Im Laufe des Refactorings „Fachlogik extrahieren“ wurde der Aufgabenbereich der Ausstatter ge-

schärft. Die Architektur sieht jetzt vor, dass Ausstatter die Items nicht mehr bearbeiten. In Java ist

es nicht möglich, zuzusichern, dass ein Objekt von einem anderen nicht verändert wird. Da dies

jedoch gewünscht ist, muss nach Alternativen gesucht werden. Die Items könnten den Ausstat-

tern unter einer Schnittstelle zur Verfügung gestellt werden, die nur einen Teil der eigentlichen

Schnittstelle enthält, nämlich nur die Methoden, die die Objekte nicht verändern. Analog dazu,

sollte auch die ItemEditBean nicht von den Ausstattern verändert werden.

Darüber hinausgehend, sollte es überprüfbare Regeln geben, die sicherstellen, dass aus den JSPs

nur auf Fragmente zugegriffen wird und nicht auf die ItemEditBean oder andere Klassen. Eine

solche Regel würde die Einhaltung der Architektur sicherstellen.

Es konnte nicht die gesamte Fachlogik extrahiert werden. Im Laufe zukünftiger Weiterentwicklun-

gen am JCommSy können weitere Aspekte auftauchen, die in die Logik-Schicht gehören. Durch

gezielte und aufwendige manuelle Suche ließen sich diese direkt finden und extrahieren.

Die Erkenntnisse bezüglich der Auswirkungen der Veränderungen der Architektur auf die Perfor-

mance beziehen sich in dieser Arbeit immer auf eine bereits bestehende, ausgeprägte Architektur.

Inwiefern und mit welchen Einschränkungen sie sich auch auf die initiale Architektur einer An-

wendung übertragen lassen, kann hier nicht geklärt werden.

Die Eigenschaft Performance hat viele Bereiche. In dieser Arbeit wurde der Fokus auf die Ausfüh-

rungszeit gelegt. Aufgrund des zeitlichen Rahmens der Arbeit, wurde der Aspekt Speicherauslas-

tung nur kurz behandelt. Bei genauerer Betrachtung könnte untersucht werden, ob Speicherlecks

vorliegen. Durch Speicherlecks steht der Anwendung mit zunehmender Laufzeit weniger Speicher

zur Verfügung als eigentlich vorhanden ist. Die daraus folgenden häufigeren Einsätze des Garbage

Collectors resultieren wiederum direkt in schlechterer zeitlicher Performance.

Offen bleibt die Frage inwiefern Speicher und Zeit miteinander zusammenhängen. In den un-

tersuchten Beispielen, ging eine Reduzierung der Ausführungszeit mit weniger Speicherumsatz

einher. Dies müsste genauer quantifiziert werden, indem z. B. für den Speicher Kategorien einge-

Page 103: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

8.2 Ausblick 91

führt werden bzw. die Kategorisierung um eine zweite Dimension erweitert wird.

Moderne JVMs können das Garbage Collecting nach unterschiedlichen Strategien durchführen.

Welche Strategie für eine Web-Anwendung, wie das JCommSy, die beste ist und wie groß der Ge-

samtvorteil ist, der sich durch die richtige Wahl erzielen lässt, muss an anderer Stelle untersucht

werden. Ebenso kann die Wahl der JVM und des Servlet-Containers betrachtet werden. Alle diese

Aspekte verlassen jedoch den Bereich Software-Architektur und zielen mehr auf die Optimierung

des laufenden JCommSy hin. Das Gleiche gilt für die Wahl des Datenbanksystems und für Opti-

mierungen der Datenbank auf das JCommSy.

Es könnte versucht werden, die Datenbank zu optimieren, z. B. indem sie auf das Benutzungsprofil

durch das JCommSy abgestimmt und konfiguriert wird oder eine alternative Datenbank verwendet

wird. Das Umsteigen von einem relationalen auf ein objektrelationales oder ein objektorientiertes

Datenbankmodell hat Auswirkungen, sowohl auf die Performance, als auch auf die Architektur

der Anwendung [ZR01]. Eine solche Migration wäre ein weiterer Ansatzpunkt, der allerdings

schlecht am JCommSy durchgeführt werden kann, da die Datenbank derzeit gleichzeitig von zwei

Systemen verwendet wird.

Eine im Rahmen dieser Arbeit offen gebliebene Frage ist, inwiefern sich die eingesetzten Rah-

menwerke auf die Performance auswirken. Ein möglicher Ansatz wäre, testweise das Hibernate

Rahmenwerk auszutauschen, bzw. SQL-Anfragen in der Service-Schicht zu erzeugen und direkt

auf die Datenbank zuzugreifen. Desweiteren bietet Hibernate die Möglichkeit externe Caches ein-

zubinden. Die Auswirkungen und richtige Konfiguration dieser könnten untersucht werden.

Als Alternative zu den JSPs könnte untersucht werden, wie die Performance sich verändert, wenn

die resultierende HTML-Seite direkt im Servlet in die HTTP-Antwort geschrieben würde. Diese

Untersuchungen sind jedoch nur dann sinnvoll, wenn Performance ein hartes Kriterium ist, weil

sie mit erheblichen Nachteilen für die Architektur verbunden sind.

Web-Anwendungen werden in der Regel von vielen Benutzern gleichzeitig verwendet. Damit

kommt, im Gegensatz zu Desktop-Anwendungen, der Aspekt der Nebenläufigkeit und des Ver-

haltens unter Last hinzu. Beide Aspekte wurden in dieser Arbeit fast vollständig unberücksichtigt

gelassen. Sowohl in Bezug auf die Komplexität der Fragestellung, als auch bezüglich des Auf-

wands, sind sie eine eigene Arbeit wert.

Die durchgeführten Optimierungen haben den Quelltext verändert und dabei teilweise Komplexi-

tät hinzugefügt. Im Rahmen dieser Arbeit konnte nicht detailliert erfasst werden, wie groß diese

Komplexität ist. In weiteren Untersuchungen könnte herausgearbeitet werden, ob der resultierende

Quelltext schwieriger zu lesen und fehleranfälliger ist und inwieweit sich generell die Komplexitä-

ten durch Optimierungen verändern. Dafür wären, neben einer genaueren Betrachtung des Begriffs

Komplexität, empirische Untersuchungen mit mehreren Entwicklern an mehreren Optimierungen

nötig.

Dieser Ausblick verdeutlicht, dass die Gebiete Architektur und Performance weitere offene Fragen

bieten. Die Bedeutung dieser Aspekte wird nicht geringer werden. Die Ergebnisse und Konzepte

dieser Arbeit können Ansatzpunkte für weitere Arbeiten sein.

Page 104: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

92 Kapitel 8 Schlussbemerkungen

Page 105: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

93

Literaturverzeichnis

[And03] ANDRESEN, Andreas: Komponentenbasierte Softwareentwicklung : mit MDA,

UML und XML. München : Hanser, 2003. – ISBN 3–446–22282–0

[BA04] BECK, Kent ; ANDRES, Cynthia: Extreme Programming Explained : Embrace

Change (2nd Edition). Addison-Wesley Professional, 2004. – ISBN 0–321–

27865–8

[BCK98] BASS, Len ; CLEMENTS, Paul ; KAZMAN, Rick: Software Architecture in Practi-

ce. Addison-Wesley Longman Publishing Co., Inc., 1998. – ISBN 0–201–19930–0

[Ben99] BENTLEY, Jon: Algorithm Alley: Code Tuning in Context. In: Dobb’s Journal of

Software Tools 24 (1999), Mai, Nr. 5, S. 125–126, 128. – ISSN 1044–789X

[BGWA08] BLOCH, Joshua ; GOSLING, James ; WILSON, Steve ; ARNOLD, Ken: Effective

Java (2nd Edition) (The Java Series). 2. Boston, MA, USA : Addison-Wesley

Longman Publishing Co., Inc., 2008. – ISBN 0–321–35668–3

[BH09] BRACHA, Gilad ; HAMILTON, Graham: JSR 294: Improved Modularity Support

in the JavaTM Programming LanguageGilad Bracha. http://jcp.org/en/jsr/

detail?id=294. Version: Januar 2009, Abruf: 15.02.2009

[BHM07] BINDER, Walter ; HULAAS, Jarle ; MORET, Philippe: Advanced Java bytecode

instrumentation. In: PPPJ ’07: Proceedings of the 5th international symposium

on Principles and practice of programming in Java. New York, NY, USA : ACM,

2007. – ISBN 978–1–59593–672–1, S. 135–144

[BHRS07] BEEGER, Robert F. ; HAASE, Arno ; ROOCK, Stefan ; SANITZ, Sebastian: Hi-

bernate: Persistenz in Java-Systemen mit Hibernate 3.2 und dem Java Persistence

API. 2., überarb. und erw. A. dpunkt.verlag, 2007. – ISBN 978–3–89864–447–1

[BMIS04] BALSAMO, Simonetta ; MARCO, Antinisca D. ; INVERARDI, Paola ; SIMEONI,

Marta: Model-Based Performance Prediction in Software Development: A Survey.

In: IEEE Trans. Softw. Eng. 30 (2004), Nr. 5, S. 295–310. – ISSN 0098–5589

[BPKL06] BECKER-PECHAU, Petra ; KARSTENS, Bettina ; LILIENTHAL, Carola: Automati-

sierte Softwareüberprüfung auf der Basis von Architekturregeln. In: BIEL, Bettina

(Hrsg.) ; BOOK, Matthias (Hrsg.) ; GRUHN, Volker (Hrsg.): Software Engineering

Bd. 79, GI, 2006 (LNI). – ISBN 3–88579–173–0, S. 27–37

[BRZ07] BLEEK, Wolf-Gideon (Hrsg.) ; RAASCH, Jörg (Hrsg.) ; ZÜLLIGHOVEN, Heinz

(Hrsg.): Software Engineering 2007, Fachtagung des GI-Fachbereichs Software-

Page 106: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

94 Literaturverzeichnis

technik, 27.-30.3.2007 in Hamburg. Bd. 105. GI, 2007 (LNI). – ISBN 978–3–

88579–199–7

[Bul00] BULKA, Dov: Server-Side Programming Techniques. Boston, MA, USA :

Addison-Wesley Longman Publishing Co., Inc., 2000. – ISBN 0–201–70429–3

[CKK02] CLEMENTS, Paul ; KAZMAN, Rick ; KLEIN, Mark: Evaluating Software Archi-

tectures. Addison-Wesley, 2002 (SEI Series in Software Engineering)

[CT05] COMMSY-TEAM: CommSy BenutzerInnenhandbuch Kontext: Hochschule, 2005.

http://www.commsy.net/uploads/Software/commsy_nutzungshandbuch.

pdf, Abruf: 15.02.2009

[Dar09] DARICILI, Ilker: Entwicklung eines J2ME-Clients für eine bestehende Web-

Anwendung - Auswirkungen der Integration auf Architektur, Kontrollfluss und Be-

nutzungsmodell, Universität Hamburg, Diplomarbeit, 2009

[Dmi04] DMITRIEV, M.: Selective profiling of Java applications using dynamic bytecode

instrumentation. In: ISPASS ’04: Proceedings of the 2004 IEEE International

Symposium on Performance Analysis of Systems and Software. Washington, DC,

USA : IEEE Computer Society, 2004. – ISBN 0–7803–8385–0, S. 141–150

[ej-08] EJ-TECHNOLOGIES GMBH: JProfiler Manual, 2008. http://resources.

ej-technologies.com/jprofiler/help/doc/help.pdf, Abruf: 15.02.2009

[FH08] FISCHER, Peter ; HOFER, Peter: Lexikon der Informatik. Springer-Verlag, 2008.

– 966 S.

[Flo07] FLOYD, Christiane: Architekturzentrierte Softwaretechnik. In: [BRZ07], S. 19–24

[Fow99] FOWLER, Martin: Refactoring: Improving the Design of Existing Code. Boston,

MA, USA : Addison-Wesley Professional, 1999. – ISBN 0–201–48567–2

[GHJV95] GAMMA, Erich ; HELM, Richard ; JOHNSON, Ralph ; VLISSIDES, John: De-

sign Patterns: Elements of Reusable Object-Oriented Software. Reading, MA :

Addison-Wesley, 1995

[Gla97] GLASS, Robert L.: Software runaways—some surprising findings. In: SIGMIS

Database 28 (1997), Nr. 3, S. 16–19. – ISSN 0095–0033

[Gro00] GROUP, IEEE Architecture W.: IEEE Std 1471-2000, Recommended practice

for architectural description of software-intensive systems / IEEE. IEEE, 2000. –

Forschungsbericht. – i–23 S.

[Ham97] HAMILTON, Graham: JavaBeans Specification / Sun Microsystems, inc. 1997. –

Forschungsbericht

Page 107: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

Literaturverzeichnis 95

[HMRD05] HACKNEY, Ruth ; MOMII, Leigh ; RIGGS, Catrin ; DINGLE, Adair: Profiler tools

selection for curricular support. In: J. Comput. Small Coll. 21 (2005), Nr. 1, S.

177–182. – ISSN 1937–4771

[HN99] HEYDON, Allan ; NAJORK, Marc: Performance limitations of the Java core li-

braries. In: JAVA ’99: Proceedings of the ACM 1999 conference on Java Grande.

New York, NY, USA : ACM, 1999. – ISBN 1–58113–161–5, S. 35–41

[Hoh07] HOHMANN, Christoph: Softwarearchitektur von J2EE Web-Applicationen mit

Components am Beispiel von AJAX, Universität Hamburg, Diplomarbeit, 2007

[hpS] Homepage zum Softwaretomographen. http://www.software-tomography.

de/, Abruf: 15.02.2009

[HQGv02] HARKEMA, M. ; QUARTEL, D. ; GIJSEN, B. M. M. ; VAN DER MEI, R. D.: Per-

formance monitoring of java applications. In: WOSP ’02: Proceedings of the 3rd

international workshop on Software and performance. New York, NY, USA :

ACM, 2002. – ISBN 1–58113–563–7, S. 114–127

[ISO01] ISO: International Standard ISO/IEC 9126, Information technology - Product

Quality - Part1: Quality Model / International Standard Organization. 2001. –

Forschungsbericht

[JB02] JANNECK, Michael ; BLEEK, Wolf-Gideon: Project-based Learning with Comm-

Sy. In: Computer Support for Collaborative Learning: Foundations for a CSCL

Community Bd. CSCL 2002, Stahl, Garry, January 2002, S. 509–510

[Jee05] JEENICKE, Martti: Architecture-Centric Software Migration of Web-based Infor-

mation Systems. In: IRIS28: Proceedings of the 28. Conference on Information

Systems Research in Scandinavia, 2005

[Kau03] KAUPPI, Tarja: Performance analysis at the software architectural level, Univer-

sity of Oulu, Diplomarbeit, 2003

[KBT05] KALIBERA, Tomás ; BULEJ, Lubomír ; TUMA, Petr: Quality Assurance in Per-

formance: Evaluating Mono Benchmark Results. In: [RMS+05], S. 271–288

[KHB06] KOZIOLEK, Heiko ; HAPPE, Jens ; BECKER, Steffen: Parameter Dependent Per-

formance Specifications of Software Components. In: HOFMEISTER, C. (Hrsg.)

et al.: Quality of Software Architectures Bd. 4214, Springer-Verlag, 2006 (LNCS),

S. 163–179

[Knu74] KNUTH, Donald E.: Structured Programming with go to Statements. In: ACM

Comput. Surv. 6 (1974), Nr. 4, S. 261–301. – ISSN 0360–0300

Page 108: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

96 Literaturverzeichnis

[Kun06] KUNE, Alexander: Leistungsbewertung von J2EE-Anwendungen - Entwicklung

einer Plattform zur generischen Leistungsbewertung von Anwendungen mit Mehr-

schichtarchitektur, Universität Hamburg, Fachbereich Informatik, Verteilte Syste-

me und Informationssysteme, Diplomarbeit, 4 2006

[Kur02] KURNIAWAN, B.: Java for the Web with Servlet, JSP, and EJB: A Developer’s

Guide to Scalable J2EE Soultions. New Riders Publishing Thousand Oaks, CA,

USA, 2002

[Lea98] LEA, D.: Steps Toward Understanding Performance in Java. In: HCW ’98: Pro-

ceedings of the Seventh Heterogeneous Computing Workshop. Washington, DC,

USA : IEEE Computer Society, 1998. – ISBN 0–8186–8365–1, S. 171

[Lil08] LILIENTHAL, Carola: Komplexität von Softwarearchitekturen, Stile und Strategi-

en, Universität Hamburg, Diss., 2008

[Lin05] LINK, Johannes: Softwaretests mit JUnit. 2. Heidelberg : dpunkt.verlag, 2005. –

ISBN 3–89864–325–5

[Mac82] MACLENNAN, B. J.: Values and objects in programming languages. In: SIGPLAN

Not. 17 (1982), Nr. 12, S. 70–79. – ISSN 0362–1340

[Mey92] MEYER, Bertrand: Applying “Design by Contract”. In: Computer 25 (1992), Nr.

10, S. 40–51. – ISSN 0018–9162

[MM06] MARCO, Antinisca D. ; MIRANDOLA, Raffaela: Model Transformation in Soft-

ware Performance Engineering. In: HOFMEISTER, C. (Hrsg.) et al.: Quality of

Software Architectures Bd. 4214, Springer-Verlag, 2006 (LNCS), S. 95–110

[MyS06] MYSQL AB: MySQL 5.0 Reference Manual, 2006. http://dev.mysql.com/

doc/refman/5.0/en/index.html, Abruf: 15.02.2009

[Par72] PARNAS, D. L.: On the criteria to be used in decomposing systems into modules.

In: Commun. ACM 15 (1972), Nr. 12, S. 1053–1058. – ISSN 0001–0782

[RH06] REUSSNER, Ralf ; HASSELBRING, Wilhelm: Handbuch der Software-Architektur.

1. Aufl. dpunkt.verlag, 2006. – ISBN 3–89864–372–7

[RMS+05] REUSSNER, Ralf (Hrsg.) ; MAYER, Johannes (Hrsg.) ; STAFFORD, Judith A.

(Hrsg.) ; OVERHAGE, Sven (Hrsg.) ; BECKER, Steffen (Hrsg.) ; SCHROEDER,

Patrick J. (Hrsg.): Quality of Software Architectures and Software Quality, First

International Conference on the Quality of Software Architectures, QoSA 2005

and Second International Workshop on Software Quality, SOQUA 2005, Procee-

dings. Bd. 3712. Springer, September 20-22 2005 (Lecture Notes in Computer

Science). – ISBN 3–540–29033–8

Page 109: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

Literaturverzeichnis 97

[Sch05] SCHARPING, Arne: Architekturvereinbarungen des JCommSys, Universität Ham-

burg, Diplomarbeit, December 2005. – 28 S.

[Sch07] SCHMALENBACH, Christof: Performancemanagement für serviceorientierte

Java-Anwendungen. Springer-Verlag, 2007 (Xpert-press). – ISBN 978–3–540–

36631–7

[Sch08a] SCHARPING, Arne: Automatisierte Prüfung von Architekturregeln zur Entwick-

lungszeit, Universität Hamburg, Diplomarbeit, 2008

[Sch08b] SCHWENTNER, Henning: Wider die enge Kopplung: Große Refactorings in einem

Prozess zur Entflechtung von Anwendung und Rahmenwerk, Universität Hamburg,

Diplomarbeit, 2008

[Shi00] SHIRAZI, Jack: Java Performance Tuning. O’Reilly, 2000. – ISBN 0–596–00015–

4

[SM02] SIMON, Frank ; MEYERHOFF, Dirk: OO-Metriken zeigen grosse Qualitätspo-

tenziale in komplexen Softwaresystemen. In: Objektspektrum Bd. 6, 2002, S. S.

28–35

[Sun99] SUN MICROSYSTEMS, Inc: White Paper: The Java HotSpot Performance Engine

Architecture. http://java.sun.com/products/hotspot/whitepaper.html.

Version: 1999, Abruf: 15.02.2009

[Sv06] SEEMANN, Jochen ; VON GUDENBERG, Jürgen W.: Software Entwurf mit UML2.

2. Springer-Verlag, 2006 (Xpert.press). – ISBN 3–540–30949–7

[SW00] SMITH, Connie U. ; WILLIAMS, Lloyd G.: Software Performance Antipatterns.

In: Proceedings of the Second International Workshop on Software and Perfor-

mance (WOSP2000), Technology, Inc, 2000, S. 127–136

[SW02] SMITH, Connie U. ; WILLIAMS, Lloyd G.: New Software Performance AntiPat-

terns: More Ways to Shoot Yourself in the Foot. In: 28th International Computer

Measurement Group Conference, Computer Measurement Group, December 2002

(Int. CMG Conference), S. 667–674

[SWLM02] SVAHNBERG, Mikael ; WOHLIN, Claes ; LUNDBERG, Lars ; MATTSSON, Micha-

el: A method for understanding quality attributes in software architecture structu-

res. In: SEKE ’02: Proceedings of the 14th international conference on Software

engineering and knowledge engineering. New York, NY, USA : ACM, 2002. –

ISBN 1–58113–556–4, S. 819–826

[Tat01] TATE, B.A.: Bitter Java. Manning Publications Co. Greenwich, CT, USA, 2001

Page 110: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

98 Literaturverzeichnis

[Thi09] THIESEN, Sönke: Verbesserung von Testbarkeit, Entwicklungskomplexität und

Architektur – Austausch der Oberflächentechnologie einer Web-Anwendung, Uni-

versität Hamburg, Diplomarbeit, 2009

[TSL04] TURAU, Volker ; SALECK, Krister ; LENZ, Christopher: Web-basierte Anwen-

dungen entwickeln mit JSP 2: Einsatz JSTL, Struts, JSF, JDBC, JDO, JCA.

dpunkt.verlag, 2004

[Tur00] TURAU, Volker: Java Server Pages Dynamische Generierung von Web-

Dokumenten. Heidelberg : dpunkt.verlag, 2000

[uml05] OBJECT MANAGEMENT GROUP, INC: UML Profile for Schedulability, Perfor-

mance, and Time. 2005 (1.1). – Forschungsbericht

[Ven96] VENNERS, Bill: Inside the Java Virtual Machine. New York, NY, USA : McGraw-

Hill, Inc., 1996. – ISBN 0–07–913248–0

[WK00] WILSON, Steve ; KESSELMAN, Jeff: Java Platform Performance: Strategies and

Tactics. Boston, MA, USA : Addison-Wesley Longman Publishing Co., Inc., 2000.

– ISBN 0–201–70969–4

[WKKRSS01] WERMKE, Matthias (Hrsg.) ; KLOSA, Annette (Hrsg.) ; KUNKEL-RAZUM, Ka-

thrin (Hrsg.) ; SCHOLZE-STUBENRECHT, Werner (Hrsg.): Duden. Bd. Band 5:

Duden. Das Fremdwörterbuch. 7., neu bearbeitete und erweiterte. Mannheim :

Dudenverlag, 2001

[WS02] WILLIAMS, Lloyd G. ; SMITH, Connie U.: PASASM: a method for the perfor-

mance assessment of software architectures. In: Proceedings of the Third Interna-

tional Workshop on Software and Performance (WOSP2002), ACM Press, 2002,

S. 179–188

[Z+98] ZÜLLIGHOVEN, Heinz et al.: Das objektorientierte Konstruktionshandbuch nach

dem Werkzeug & Material-Ansatz. Heidelberg : dpunkt.verlag, 1998. – ISBN

3–932588–05–3

[ZLMG08] ZEITNER, Alfred ; LINNER, Birgit ; MAIER, Martin ; GÖCKELER, Thorsten:

Spring 2.5: Eine pragmatische Einführung. 1. München : Addison-Wesley, 2008.

– ISBN 978–3–8273–2622–5

[ZR00] ZHANG, W.P. ; RITTER, Norbert: Leistungsuntersuchungen hinsichtlich der Nut-

zung von (O)RDBVS als persistente Objektsysteme. In: Grundlagen von Daten-

banken, 2000, S. 111–115

[ZR01] ZHANG, W.P. ; RITTER, Norbert: Leistungsuntersuchung von ORDB-gestützten

objektorientierten Anwendungssystemen. In: HEUER, A. (Hrsg.): Tagungs-

band der GI-Fachtagung ’Datenbanksysteme in Büro, Technik und Wissenschaft’

(BTW’2001), Springer-Verlag, 3 2001, S. 227–243

Page 111: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

99

Anhang A

Messergebnisse

Client Client/Asserts Server Server/OptimiertSchicht Zeit [s] Anteil Zeit [s] Anteil Zeit [s] Anteil Zeit [s] Anteilservice 443,2 43,24 % 428,7 40,74 % 377,8 36,90 % 447,3 37,33 %util 37,7 3,68 % 47,8 4,54 % 44,6 4,36 % 63,8 5,33 %presentation 450,8 43,97 % 483,3 45,93 % 512,5 50,06 % 584,3 48,77 %item 81,0 7,90 % 76,9 7,30 % 74,6 7,28 % 83,0 6,98 %domainvalue 7,8 0,76 % 11,5 1,09 % 7,4 0,72 % 5,1 0,43 %migration 2,5 0,25 % 2,5 0,24 % 3,4 0,33 % 13,1 1,09 %logic 2,1 0,21 % 2,7 0,26 % 3,6 0,35 % 1,5 0,12 %Gesamt 1.025 100 % 1.052 100 % 1.024 100 % 1.198 100 %

Tabelle A.1: Vergleich der unterschiedlichen JVM Modi (Stand: 2. Dezember 2008)

Page 112: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

100 Anhang A Messergebnisse

PHP WelcomePHP Choose Portal

PHP Login as httpunitPHP

PHP Change roomswitch to announcement index

switch to date indexswitch to group index

open detail announcement directlyswitch to announcement (20 entries)

select next 20 entries announcementselect detail announcement

select detail groupselect announcement detail

next announcement detailannouncement edit

POST announcement edit saveannouncement detail

select group detailjoin a group

leave a groupcreate new announcement

save new announcementdelete created announcement

create new datesave new date

delete created datecreate new group

save new groupdelete created group

display 10 items of group indexdisplay ALL items of group index

search for "TEST"select TestGroup (group detail)

select „save page“expand creator info

sort by "bearbeitet von"sort by "bearbeitet von" rev

sort by "Titel"sort by "bearbeitet"

PHP logout

0 500 1000 1500 2000 2500 3000 3500

144

605

1074

747

2976

717

529

414

256

564

731

259

514

267

256

472

123

264

220

236

243

161

117

652

170

116

623

158

402

531

285

488

308

227

688

220

801

816

812

789

1155

Zeit in Millisekunden

An

fra

ge

Abbildung A.1: Durchschnittliche Antwortzeiten des JCommSy ohne Profiler (Stand: Okt. 2008)

Page 113: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

101

Abbildung A.2: Gegenüberstellung der minimalen Antwortzeiten für einen Wechsel der Über-sichtsseiten mit und ohne Ajax.Der rot markierte Bereich hebt den eigentlichen Vergleich hervor.

Abbildung A.3: Gegenüberstellung der durchschnittlichen Antwortzeiten für einen Wechsel derÜbersichtsseiten mit und ohne Ajax.Der rot markierte Bereich hebt den eigentlichen Vergleich hervor.

Page 114: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

102 Anhang A Messergebnisse

Page 115: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

103

Anhang B

Testfälle

Im Folgenden wird zu jedem Testfall des Benchmarks (siehe 5.2.3) die genaue Abfolge der Ak-

tionen aufgeführt.

Übersichtsseiten : Ankündigungen→ Termine→ Gruppen→ Gruppen→ Termine→ Ankün-

digungen→ Gruppen→ Ankündigungen

Lesen : direkt von der Übersichtsseite auf eine Ankündigung (neu) → Ankündigungsübersicht

→ nächsten 20 Einträge→Ankündigung auswählen→ Gruppen→ Gruppen auswählen→Gruppen

Bearbeiten : Ankündigungen → Ankündigung auswählen → nächste Ankündigung auswählen

→ Text bearbeiten→Gruppenübersicht→Gruppe auswählen→Gruppe beitreten→Grup-

pe austreten→ Übersicht

Erstellen/Löschen : Ankündigungen → erstellen → speichern → löschen → Termine erstellen

→ speichern→ löschen→ Gruppen erstellen→ speichern→ löschen→ Gruppenübersicht

Spezialfunktionen : Gruppen→ 10 Einträge anzeigen→ alle Einträge anzeigen→ suche nach

„TEST“ → wähle DummyTestGroup → Seite speichern → „zuletzt bearbeitet von“ auf-

klappen→ Übersicht

Sortieren : Ankündigungen→ sortieren nach „bearbeitet von“→ sortieren nach „bearbeitet von“

(Absteigend) → sortieren nach „bearbeitet von“ → sortieren nach Titel → sortieren nach

bearbeitet

Page 116: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

104 Anhang B Testfälle

Page 117: Wechselwirkungen zwischen Performance und Architektur ... · More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single

Eidesstattliche Erklärung

Ich versichere, dass ich die vorstehende Arbeit selbstständig und ohne fremde Hilfe angefertigt

und mich anderer als der im beigefügten Verzeichnis angegebenen Hilfsmittel nicht bedient habe.

Alle Stellen, die wörtlich oder sinngemäß aus Veröffentlichungen entnommen wurden, sind als

solche kenntlich gemacht.

Ich bin mit einer Einstellung in den Bestand der Bibliothek des Departments Informatik einver-

standen.

Hamburg, den Unterschrift: