1
Orientation in Objects GmbH
Weinheimer Str. 6868309 Mannheim
[email protected]: 1.1
Performance Tuningbei komplexen
DomainmodellenChristian Dedek
Falk Sippach
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 2
) Akademie )) Beratung )
Java, XML und Open Source seit 1998
• Schulungen, Coaching, Weiterbildungsberatung, Train & Solve-Programme
• Methoden, Standards und Tools für die Entwicklung von offenen, unternehmens- weiten Systemen
• Schlüsselfertige Realisierung von Software• Unterstützung laufender Projekte• Pilot- und Migrationsprojekte
) Projekte )
2
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 3
Performance?
Autor unbekannt
"You need the computing power of a Pentium, 16 MB RAM and 1 GB Harddisk to run Win95.
It took the computing power of
3 Commodore 64 (C64) to fly to the Moon.
Something is wrong here, and it wasn't the Apollo."
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 4
Agenda
• Problemstellung• Navigation in Objektnetzen• Caching• Veränderung von Objektnetzen• Diverses• Lessons learned
3
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 5
Hibernate ist ein "einfaches"Persistenzframework
<<Tabelle>>Person
PERSON_ID<<PK>>FIRSTNAME....
<<Tabelle>>Adresse
ADRESSE_ID<<PK>>PERSON_ID<<FK>>STRASSE...
Collection
PersonAdresseAdresseAdresseAdresse
1 n
session.save(person);...person = session.load(Person.class, 1L);for (Adresse a : person.getAdressen) {
...}
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 6
Was ist bei komplexen Domänenmodellen?
Beleg
Gruppen
G1 G2
P11 P12 P21 P101 P102
Positionen
Positionen Positionen
Entität
Collection
4
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 7
Performance-Probleme mit Hibernate ?
• Hibernate verursacht natürlich Overhead– durch OR-Mapping, Dirty-Checking, DB-Unabhängigkeit, ...
• Hibernate bringt auch Vorteile: z. B. Caches– aber ggf. nutzlos durch falsche Verwendung
• Was tun?– Optimierungsmöglichkeiten von Hibernate ausnutzen– Stored Procedures oder direkt SQL aus Hibernate aufrufen (DB
spezifische Abfrage-Optimierung)– Alternativen zu Hibernate: JDBC, iBatis, ...
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 8
Vorgehensweise Performance-Tuning
• Durchführung von Last- und Performanztests• Testszenarien (aus Use Cases) und deren Qualitätsziele festlegen
– sinnvolle Testdaten (wenn möglich auch Massendaten für Lasttests)• Problem Testdatenbeschaffung und -reproduktion
– Testszenarien sollten mit vertretbarem Aufwand wiederholbar sein– ev. Definition von Key Performance Indikator
• Testläufe müssen reproduzierbar sein– vor Performance-Tuning muß das mehrfache Ausführen eines
Testlaufs gleiche oder zumindest ähnliche Ergebnisse liefern• Scheduling, Netzwerk...
• kleine Performance-Iterationen– ein spezielles Tuning und danach Testlauf um Effekt zu erkennen
• Einsatz spezialisierter Werkzeuge
5
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 9
Aktivitäten bei der Testdurchführung
Zielbestimmungen und Mengengerüst festlegen
Testumgebung und Rahmenbedingungen erfassen
Testplan festlegen
Testszenarien festlegen
Test durchführen
Analyse durchführen
Maßnahmen durchführen
Misserfolg analysieren
[gewichtiger Fehler]
[nicht aussagekräftig]
[erfolgreich][nicht erfolgreich]
[nicht behebbar][behebbar]
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 10
Lasttesttreiber - The Grinder 3
helloWorldService.pyfrom net.grinder.script.Grinder import grinderfrom net.grinder.script import Testfrom examples.webservices.basic.javaclass import HelloWorld_Implfrom java.lang import System
System.setProperty( "javax.xml.rpc.ServiceFactory", "weblogic.webservice.core.rpc.ServiceFactoryImpl")
webService = HelloWorld_Impl("http://localhost:7001/basic_javaclass/HelloWorld?WSDL")
port = webService.getHelloWorldPort()portTest = Test(1, "JAXP Port test").wrap(port)
class TestRunner: def __call__(self): result = portTest.sayHello(grinder.threadID, grinder.grinderID) grinder.logger.output("Got '%s'" % result)
6
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 11
Lasttestanalysen durchführen
Skript
Anz
ahl I
nsta
nzen
Anzahl Testläufe
Analyseunterstützung
Speichern als PNG
Grinder-Import
logs
data_xxx.log
error_xxx.log
skript1
skript2
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 12
Werkzeuge - Monitoring Tools
• Profiler: z. B. JProfiler, JProbe, PerformaSure• JMX-Tooling: z. B. JConsole, AdventNet, MC4J, ...
7
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 13
Hibernate Statistics:JConsole, Statsviewer
<bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter"> <property name="beans"> <map> <entry key="Hibernate:name=statistics"> <ref local="statisticsBean" /> </entry> </map> </property></bean>
<bean id="statisticsBean" class="org.hibernate.jmx.StatisticsService"> <property name="statisticsEnabled"> <value>true</value> </property> <property name="sessionFactory"><ref bean="sessionFactory"/></property></bean>
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 14
Werkzeuge - DB-Analyzer
• Tracer: z. B. P6Spy, IronTrack SQL, Elvyx• SQL-Clients: z. B. Toad, SQL-Developer (für Oracle DB)
8
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 15
Live-Demo
• Anwendung steht für mehrere Minuten• Ermittlung der Ursache per P6Spy und IronTrack SQL
– eine bestimmte DB-Abfrage dauert sehr lange• per SQL-Tool (Explain-Plan, Autotrace)
• 1000 Einträge aus Tabelle1 löschen– "delete from Tabelle1 where ..."– Full Table Scan in Tabelle2 (Constraint-Überprüfung)
• Ursache: Index auf TABELLE1_FK-Spalte fehlt
<<Tabelle>>Tabelle1
ID <<PK>>....
<<Tabelle>>Tabelle2
ID <<PK>>TABELLE1_FK <<FK>>...
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 16
Autotrace-Auswertung in SQL-Tool:Optimierung durch Einführung von DB-Indizes
• ohne Index
• mit Index
9
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 17
Agenda
• Problemstellung• Navigation in Objektnetzen• Caching• Veränderung von Objektnetzen• Diverses• Lessons learned
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 18
Java Virtual Machine
„Hibernate in 30 Sekunden“
*.classJava Compiler
Hibernate
DB hibernate.cfg.xml
*.hbm.xml
10
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 19
Schichtentrennung
Business Layer
Persistence Layer
Session Transaction Query
SessionFactory
Configuration
Interceptor
UserType
JNDI JDBC JTA
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 20
Optimierte Navigation in komplexenObjektnetzen/Relationen ?
Mannheim
GreenSupply
Hauptstrasse 174G7/2
Heidelberg<<Tabelle>>
Person
PERSON_ID<<PK>>FIRSTNAME....
<<Tabelle>>Adresse
ID<<PK>><<FK>>STRASSE...
id plzpositionstrasse
11
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 21
Relationen navigieren
• Navigationsgeschwindigkeit optimieren– vollständiges Objektnetz in Speicher laden– komplexe Netze brauchen viel Speicher
• Speicherverbrauch optimieren– Relationen werden bei Bedarf nachgeladen– sog. N+1 Problem
• mögliche Lösungen– Batch Fetching– Subselect Fetching– Join Fetching (Achtung: Karthesisches Produkt)– HQL– Filter
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 22
N+1 Problem
List<Person> allPersons = session.createQuery("from Person").list();// List<Person> allPersons = session.createCriteria(Person.class).list();
Map<Person, Address> highestAddresss = new HashMap<Person, Address>();for (Person person : allPersons) { Address highestAddress = null; for (Address address : person.getAddresss() ) { // Initialize the coll. if (highestAddress == null) highestAddress = address; if (address.getPLZ() > highestAddress.getPLZ()) highestAddress = address; } highestAddresses.put(person, highestAddress);}
1 select für Liste der Entitäten+ n select für jede navigierte Relation
12
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 23
Batch-Fetching
<set name="Addresss" inverse="true" batch-size="10">
<key column="Person_ID"/> <one-to-many class="Address"/>
</set>
1 select für Liste der Entitätenselect Persons...
+ n/batchsize selects für jede Gruppe navigierter Relationenselect a.* from Address a where a.Person_ID in (?<,?>)
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 24
Laden mit Subselects
<set name="Addresss" inverse="true" fetch="subselect">
<key column="Person_ID"/> <one-to-many class="Address"/>
</set>
1 select für Liste der Entitätenselect Persons...
+ 1 select für alle navigierte Relationenselect a.* from Address awhere a.Person_ID in (select p.Person_ID from Person p)
13
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 25
Laden mit joins
•Fetchplan<set name="addresses" inverse="true" fetch="join">
<key column="Person_ID"/> <one-to-many class="Address"/>
</set>
1 select für Liste der Entitäten mit allen navigierbaren Relationenselect p.*, a.*from Person pleft outer join Address a on p.Person_ID = a.Person_ID
•besonders interessant für n-1-Relation
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 26
Laden mit expliziten Queries
Alternative Abfrage für eine Liste der Entitäten mit allen navigierbarenRelationen in spezifischem Anwendungsszenario
List<Person> allPersons =session.createQuery("from Person p left join fetch p.Addresss").list();
List<Person> allPersons = session.createCriteria(Person.class) .setFetchMode("addresses", FetchMode.JOIN) .list();// Iterate through the collections...
Es resultiert eine Datenbankanfrage
select p.*, a.*from Person pleft outer join Address a on p.Person_ID = a.Person_ID
14
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 27
Kartesische Produkte
id Fla..Bewoh..name id satzleistungname id aktivornamename
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 28
• mit jeder Relation potenziert sich die Größe des resultierendenAnfrageergebnisses– DB-Server
• Abfragezeit• IO-Aufwand
– Applikation• Speicherverbrauch• Mappingaufwand in Hibernate
Kartesische Produkte
15
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 29
Filter
• Mapping<class name=“City" table=“KA_STADT" lazy="false">.. <set name=“dezernenten“ table=“KA_DEZERNENT“ cascade="all,delete-orphan" lazy="false"> <key foreign-key="FK_KA_DEZERNENTEN“ column=“KA_STADT_ID" not-null="true" /> <one-to-many class="de.ex.Dezernent" /> <filter name="limitbyParty “ condition=“PARTY_NAME = :partId"/> </set>..</class>
• AnwendunggetHibernateTemplate().enableFilter("limitByParty").setParameter(“partId",“DIE GRAUEN“);..
getHibernateTemplate().getSessionFactory().getCurrentSession().disableFilter("limitbyParty");
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 30
Feintechniken
• Value types– Komponente im Kompositum (fehlender Lebenszyklus)
• extra Lazy Proxy Collection– ev. nützlich bei sehr großen Assoziationsmengen
• Lazy Attribute Fetching– bei LOB-Feldern bereits implizit
• Interception statt Proxies– Aufwand eigenimplementierter Lösungen?
16
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 31
Feintuning
• zu komplexe DB-Anfragen– DB-spezifische Optimierung der execution plans– Minimierung von join-fetches
• zu viele DB-Anfragen– fetch-Typen definieren
• eher an der Abfrage als global• Batchsizes an Verarbeitungsgruppen(Screens) orientieren
– Alternative - Caching erwägen ?
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 32
Optimierungsstrategie
• Ausgangspunkt: Lazy Default-Fetch-Plan– n-1/1-1-Relationen mit lazy=false
• dann: Szenarien bezogenes Aufzeichnen• der auslösenden Hibernateanfragen• der resultierenden DB-anfragen
• daraus: Optimierung der Zahl und Komplexität der resultierendenDB-Anfragen durch Anpassung der Fetchstrategie der initiiertenHibernateanfragen– spezifische Optimierung einer Anfrage– seltener Optimierung des globalen Fetchplans
• Vorsicht Kostenfalle: manuelle Testausführung– globale Fetchplanänderungen erfordern Regressionstest– Lernkurve beachten
17
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 33
bekannte Architektur Muster
• Open Session in View Pattern– Navigation nutzt Sessioncache
• aber nutzt globale Fetchoptimierung(side Effects ?)– Query wirkt nicht auf Session Cache
• Vorteil optimierter spezifischer Fetchplan
• spezifische Service Fassade– Ausgangspunkt Navigation über Session– Optimierung über spez. Finder in DAO– DAO-Schnittstelle wird breiter/Wartungsaufwand
• generisches DAO (Preload Pattern JavaMagazin 4/08)– schmale Finder-Schnittstelle– keine spezifischer Fetch-Plan
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 34
Agenda
• Problemstellung• Navigation in Objektnetzen• Caching• Veränderung von Objektnetzen• Diverses• Lessons learned
18
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 35
Live Demo: Hibernate Statistics
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 36
Caches in Hibernate
• First-Level:– immer aktiviert– nur solange die eine Session offen ist– funktioniert nur bei Aufruf von load/get und bei Assoziationen-Fetch– funktioniert nicht bei Queries
• Second-Level:– muß erst aktiviert werden– Konfiguration nicht trivial– Query-Cache muß separat aktiviert werden
19
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 37
Cache-Konfiguration
• in Hibernate-Settings aktivieren– CacheProvider (EHCache, OSCache, SwarmCache, TreeCache)– use_second_level_cache=true
• Cache Regions (angeben für Klassen, Collections oder Queries)– Usecase spezifisch optimieren– usage: Caching Strategie
• read-only:beste Performance• nonstrict-read-write: nur für nicht konkurrierende Zugriffe• read-write: gewährleistet read-commited• transactional: nur bei JTA-Umgebungen
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 38
Gefahren bei Second Level Caches
• andere Applikationen, welche die DB ändern– Cache muß regelmäßig validiert werden
• zu viele schreibende Zugriffe– Cache-Miss größer als Cache-Hit: schlechtes Cache-Ratio
• zu kleine Dimensionierung des Cache– sollte aber auch nicht zu groß dimensioniert werden (GC dauert
länger, längere Validierungsphase mit DB)
Performance kann sogar sinken (durch hohen Verwaltungsaufwand).
20
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 39
Problem: fehlender Cache-Hit
• Beobachtung: Session Cache arbeitet nicht richtig– immer wieder die gleichen SQL-Selects im Log-Output
• Ursache: statt mit load/get wird mit HQL-Findern gearbeitet– von AndroMDA generierter Code arbeitet mit findById– Bug mittlerweile gefixed: AndroMDA generiert jetzt session.get()
• Alternative für finder: Query-Cache einschalten
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 40
Query-Cache
• Query-Cache überhaupt erstmal einschalten
• Query-Cache speichert nur IDs– muß mit Entity-Cache zusammen arbeiten
• nur sinnvoll für häufige Abfragen mit immer gleichen Parametern• darum werden Queries defaultmäßig nicht gecached
– setCacheable(true) aufrufen!
public Object getObjectByName(String name) { Query q = session.createQuery("from Object where name = ?"); q.setParameter(0, name); q.setCacheable(true); return q.uniqueResult();}
<prop key="hibernate.cache.use_query_cache">true</prop>
21
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 41
Unwirksamer Cache
• z. B. bei Abfragen mit ständig wechselnden Parametern
• ggf. eigene Caches implementieren– insbesondere wenn immer der gleiche Datensatz geholt wird– dazu alle abzufragenden Datensätze laden und in Java vergleichen
• funktioniert nur bei überschaubarer Anzahl von Datensätzen!
hql = "from de.oio.Firma ... where validFrom <= :date and validTo >= :date";
Query q = session.createQuery(hql);for(..) {
q.setDate(..);q.list();
}
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 42
Agenda
• Problemstellung• Navigation in Objektnetzen• Caching• Veränderung von Objektnetzen• Diverses• Lessons learned
22
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 43
Collections
• Arten– Indizierte collections
• maps/lists/arrays über eine index Spalte– Sets
• Uniqueness– Bags
• keine Garantien zu Reihenfolge oder Uniqueness• Id-bag
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 44
Flushing-Probleme: Vorher
23
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 45
Hintergrund
• Hibernate Session:– 1st Level Cache, muß mit DB synchronisiert werden -> Flushing
• Flushing:– Session.flush()– Transaction.commit()– bei DB-Abfragen (Dirty Check)
• Dirty Check:– Objektänderungen so lange wie möglich in der Session vorgehalten– bei Abfragen ggf. zuerst aufgelaufene Änderungen wegschreiben– Änderungen werden ermittelt und DML-Anweisungen generiert
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 46
Probleme
• je mehr Daten in der Session, desto länger dauert Dirty Check• Flush aber oftmals gar nicht notwendig
• Lösungen:– Operationen neu ordnen– Objekte aus Session abhängen (read-only)– mit dem Flush warten bis zum Commit (write behind)– Anwendung kontrolliert explizit Flushing
• Default Flushing Verhalten ändern:– MANUAL, COMMIT, AUTO, ALWAYS
24
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 47
Nachher: Flushmode.COMMIT
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 48
Massendaten-Verarbeitung:1000 Datensätze löschen
2000 SQL-AnweisungenSession-Cache wird unnütz befüllt
eine SQL-Anweisungminimale DB-Kommunikation
for (...) {Entity e = session.load(Entity.class, id);session.delete(e);
}
String hql = "delete from Entity where idbetween ...";
session.createQuery(hql).execute();
25
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 49
Single SQL statement
• Objekte können verarbeitet werden, ohne sie vorher in Speicherzu laden (Hibernate unterstützt INSERT/UPDATE/DELETE)– update Person set gehalt = :newGehalt where status = 'Chef'
• separates Löschen von vielen Elementen ist ineffizient– session.delete()– Vorsicht: Springs HibernateTemplate.deleteAll(Collection col) iteriert
über Collection und löscht jedes Element einzeln
• Collection-Mapping Delete-Optimierung– Hibernate erzeugt einzelnes DELETE bei Collection.clear()– funktioniert nicht mit inverse="true" (bidirektionalen Beziehungen)
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 50
Stateless Session
• ideal für Ausführung von Bulk/Batch Operationen (funktioniertauch mit detached Objects)
• ähnlich einer normalen Session, aber– kein Persistenz-Kontext, kein Cache (weder 1st noch 2nd)– kein automatisches Dirty Checking oder transaktionales Write Behind– kein kaskadierendes Verhalten, ignoriert Collections– umgeht Event-Modell und Interceptoren
sessionFactory.openStatelessSession()
26
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 51
DB Performance Tuning
• DB Administratoren fragen• SQL-Dialect nach herstellerspezifische Features untersuchen
– ggf. eigenen Dialekt schreiben
• DB-Indizes– fehlen meist bei Grüne-Wiesen-Projekten– DB generiert typischerweise nur Unique-Constraints (PK, ...)– FK-Felder sollten Index erhalten, wenn Sie oft abgefragt werden– aber:
• nicht zu viele Indizes sonst leidet Insert/Update Performance• Indizes immer überprüfen, ob sie überhaupt verwendet werden
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 52
Hibernate Indizes
• Hibernate unterstützt Index-Definition in Mapping-Files
• für Properties und Assoziationsenden
<property name=".." index="idx" />
<many-to-one name=".." index="fk_idx" />
27
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 53
Agenda
• Problemstellung• Navigation in Objektnetzen• Caching• Veränderung von Objektnetzen• Diverses• Lessons learned
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 54
Probleme bei Rich-Client Architekturen
• leider oft: feingranulare Services– CRUD-Schnittstelle für jede Domain-Klasse (auch für jedes Kind)– viele Aufrufe an Backend (Netzwerkverkehr)
• bei Objektnetzen hängt teilweise der ganze Objektbaum dran– Speicherprobleme bei falschem oder fehlendem Umhängen der
Abhängigkeiten (besonders bei bidirektionalen Verbindungen)
• besser: grobgranulare Fassaden– Usecase-spezifisch– Minimierung der Aufrufe ans Backend– Verringerung der Memory-Spitzen durch weniger RMI-Kopien
28
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 55
C2 wird ans Backend geschickt und dann inCollection Children ausgetauscht
Parent
Children
C1 C2
service.method(C
2)
IN
OUT
vorher:
nachher:Parent
Children
C1 C2
Parent_1
Children_1
C1_1
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 56
Herausgelöste Objekt-Teilgraphen
• Speicher läuft voll bei Remote-Kommunikation– durch RMI erhalten wir mehrere Objekte im Speicher mit gleicher
Datenbank-Identität– diese "Kopien" enthalten ggf. wieder den kompletten (kopierten)
Objektgraphen, je nach globaler Fetching-Strategie
• GC kann Speicher nicht freiräumen, wenn noch Referenzen aufKopien des Objektgraphen bestehen– z. B. durch falsches Setzen der bidirektionale Beziehungen– Workaround für bidirektionale Beziehungen:
addChild(Child child) {this.getChildren().add(child);child.setParent(this);
}
29
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 57
Probleme Hibernate Interceptor
public interface Interceptor {
public boolean onLoad(..) throws CallbackException;public boolean onFlushDirty(..) throws CallbackException;boolean onSave(..) throws CallbackException;public void onDelete(..) throws CallbackException;[..]public void postFlush(Iterator entities) throws Callba..;
public void afterTransactionCompletion(Transaction tx);
Aufräumen des Interceptor: afterTransactionCompletion()Aber: Aufruf nur bei Hibernate-Transaktionen, nicht bei JTA
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 58
ThreadLocal bei Hibernate Interceptor
• ThreadLocal-Variable muß immer aufgeräumt werden– ThreadLocal.remove();
– ThreadLocal kann sonst Memory-Leaks verursachen
• Verwendung eines ThreadLocals im Hibernate Interceptor– bei Nicht-Hibernate-Transaktionen wird nicht aufgeräumt– ThreadLocal-Objekt bleibt also bei einer Exception im Speicher– gefixed ab Hibernate 3.2.6:
• es wird nun immer implizit eine Hibernate-Transaktion gestartet• dadurch wird Interceptor korrekt deinitialisiert
• Spring-Workaround für ältere Hibernate-Versionen:– AOP-Throw-Advice für Service-Aufrufe, der Interceptor aufräumt
30
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 59
Probleme Threadlocal
• Vergleiche– http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ThreadLocal.html– http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadLocal.html
• Der kleine Unterschied:– public void remove()
• Removes the value for this ThreadLocal
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 60
Garbage Collector Aufwand optimieren
• Genutzten Speicher minimieren– Speicher ist zwar immer billiger aber weiterhin begrenzt
• z.B. ineffizientes caching führt zu erhöhtem Bedarf an GarbageCollections
– Caching ist kein High-level-Fix für Probleme tieferer Schichte– explizite Eviction an der SessionFactory als manueller Eingriffspunkt
im API
• Bessere GC-algorithmen– hilft bei „typischen Verfügbarkeitsproblemen“
• Phänomen seit Jahrzehnten bei GC-Sprachen bekannt– paralleler GC-algorithmus auf multi-prozessor systemen– schwierig (aber notwendig) zu testen
31
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 61
Spring Bugs
• http://jira.springframework.org/browse/SPR-1690– falsche Errorcodes für Deadlocks in DB
• http://jira.springframework.org/browse/SPR-2888– Deadlock bei spezieller init– Deadlock beim Exceptionhandling von Connections
• http://jira.springframework.org/browse/SPR-3961– Running benchmarks under high loads with 8 or more concurrents
threads I see significant lock contention from the synchronized blockinorg.springframework.aop.framework.AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice. This is a significant bottleneck in ourbenchmarks.
• http://jira.springframework.org/browse/SPR-1968– wzeite readonly Session in Spring um JSF zu unterstützen
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 62
Hibernate Bugs
• http://opensource.atlassian.com/projects/hibernate/browse/HHH-2841 Deadlock im Jboss offen
• http://opensource.atlassian.com/projects/hibernate/browse/HHH-1669 mögliches Memoryleak
• http://opensource.atlassian.com/projects/hibernate/browse/HB-1246 seltener Deadlock wont fix
• Deadlocks in Treibern– http://opensource.atlassian.com/projects/hibernate/browse/HHH-1167
• Deadlocks in Pools– http://opensource.atlassian.com/projects/hibernate/browse/HHH-3189
32
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 63
Agenda
• Problemstellung• Navigation in Objektnetzen• Caching• Veränderung von Objektnetzen• Diverses• Lessons learned
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 64
Best Practices I
• Anwendung einer optimistic concurrency zur Implementierungeiner hohen Skalierbarkeit sinnvoll
• Definition einer klaren Sessionmanagement Strategy– vorteilhaft ist Einbindung in gut dokumentierte Patterns
• Default Fetch Plan für Assoziationen ist lazy– Optimierung erfolgt gemäß Kapitel 2– sehr breiter Featureset(Filter,Projektionen,Interceptoren..) zur
Optimierung
33
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 65
Best Practices II
• Definition der Caching Strategie– Festlegen welche Bereiche über Navigation (Session Cache) und
welche über Finder (Query Cache optimieren)– Entity-Cache fein anpassen und tunen
• Verständnis für Implementierungsdetails hilft beim Optimieren
• Definition einer einheitlichen flush-Strategie– Feintuning: Hibernate auto-flush vs. use case spezifische
Synchronisation
• Untersuchung der GC-Aktivitäten– Minimierung des GC-Aufwands– Erkennung (minimaler) Memoryleaks
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 66
Nichtfunktionale QM-Strategie
• Performance Meta Antipattern „Performance Afterthoughts“ istRealität in der agilen Entwicklung
• nichtfunktionales Qualitätsmanagement benötigt– fachlich richtige und realitätsnahe Testfälle– Automatisierung– Entwicklungsbegleitung– Technologische Kompetenz
• Hibernate/Spring• eingesetztes RDBMS
– Integration ins Entwicklungsteam• Empfehlung: Definition von Key Performance Indikatoren
34
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 67
Architekturelle Reife
• Die vorkonfektionierte Grobarchitektur Spring/Hibernate– hat viele gute Standardeinstellungen in Bezug auf Performanzaspekte
• in beiden Frameworks– Communities sorgen für Praxisnähe und -einsatz der Ideen– bietet bei Bedarf sehr viele Möglichkeiten für
Performanzoptimierungen• oft einfach durch reine Konfiguration
• Leistungsgrenzen der Kombination Spring/Hibernate sind amtechnologischen Gesamtstack aus JVM/OS/RDBMS/Netzwerk/IOangelehnt
© 2008 Orientation in Objects GmbH Performance Tuning bei komplexen Domainmodellen 68
Der Kaufmann rechnet - oder Reife vs.Produktivität
• POJO-Development erhöht Entwicklungsgeschwindigkeit undsenkt den technischen QM-Aufwand– fast direkte Implementierung fachlicher Modelle möglich
• rasante Entwicklung von Spring/Hibernate/Tooling seit 2003senkte bisher die Entwicklungsgeschwindigkeit– sehr hoher Entwicklungsdruck fordert Qualitätsopfer
• Vorteil: Open Source schafft hier Transparenz– erfordert ständigen KnowHow-Transfer in die Entwicklung
• gerechtfertigt durch Produktivitäts- und Qualitätssteigerungen – zwingt zu Migrationen der Infrastruktur
• Bsp. MDD-Generatoren, Konfigurations-, Buildmanagement,Codeanalysewerkzeuge
35
Orientation in Objects GmbH
Weinheimer Str. 6868309 Mannheim
[email protected]: 1.1
? ?
???
Fragen ?
Orientation in Objects GmbH
Weinheimer Str. 6868309 Mannheim
[email protected]: 1.1
Vielen Dank für IhreAufmerksamkeit !