Nie mehr weltweites Warten Performancetuning für JSF-Anwendungen Orientation in Objects GmbH Weinheimer Str. 68 68309 Mannheim Version: www.oio.de info@oio.de Ihr Sprecher Thomas Asel Trainer, Berater, Entwickler Schwerpunkte Frontend-Architektur, Entwicklung von Web-Anwendungen, Web-Performance-Optimierung http://blog.oio.de @Tom_Asel thomas.asel@oio.de 2 1
Das war in der Schachtel Lifecycle Resource Handling Komponenten- Modell Architektur- Modell Programmier- Modell viele, viele, Bibliotheken 3 Fear, Uncertainty, Doubt JSF ist doch oldschool schwerfällig schwierig langsam 4 2
Performance optimieren Auf welcher Ebene? JVM- Ebene JSF-Ebene Web- Ebene Heap-Size Garbage Collection Lifecycle Komponenten Requests Caching 5 Only 10%-20% of End-User Response-Time is spent donwloadingthe HTML document. Steve Souders - Web-Performance Guru, Yahoo 6 3
Welt-Weites-Warten Browser Servlet-Container GET /index.jsf JSF-Lifecycle "LATENZ" JSF Response Time Resource Loading GET stylesheet.css GET script.js GET logo.png RestoreView Render Response 7 Worauf haben wir Einfluss? # Resource Requests JSF-Response-Time Peering-Point-Distanz ISP User-Bandwith-Speed 8 4
Optimierungspunkte Easy Winner Performance Optimierung JSF-Spezifisch Web- Spezifisch Component Tree optimieren Lifecycle Duration reduzieren # Requests reduzieren Größe in kb reduzieren 9 Welt-Weites-Warten Browser Servlet-Container GET /index.jsf JSF-Lifecycle JSF Response Time RestoreView Render Response GET stylesheet.css GET script.js GET logo.png 10 5
JSF - Komponentenbaum UIViewRoot HtmlForm HtmlOutputText HtmlInputText HtmlOutcomeTargetLink 11 Apply Request Values Restore View Validation JSF Lifecycle Render Response Update Model Invoke Application 12 6
JSF - Komponentenbaum Wird im Lifecycle-Phase mehrfach traversiert Besonders aufwendig: Phase1: Erzeugung / Wiederherstellung Client-Side State-Saving: Deserialisierung Phase 6: Rendering 13 Dauer der Lifecylce-Phasen - Vergleichsmessung 60 50 Duration [ms] 40 30 20 10 C=1000 C=500 0 C=250 1 2 3 4 5 6 C=100 C=10 Phase Quelle: http://bit.ly/myfaces-vs-mojarra 14 7
Dauer der Lifecylce-Phasen Anteilig 50 45 40 Render Response % of Lifecycle Duration 35 30 25 20 15 Restore View Validation 10 Update Apply Model Request 5 Values Invoke 0 Application 0 1 2 3 4 5 6 7 Lifecycle Phase 15 Anzahl Components / View Beobachtet: < 50 eher selten Mittelwert ca. 200 Ausnahmefälle bis 3000 Ursache: Falscher Gebrauch von Composite Components "Dead Code": rendered="false" Trotzdem Teil des Komponentenbaumes Komplexität z.b.: verschachtelte Tabbed Panes 54 Components! 16 8
JSF Wiederverwendbare Einheiten Custom-Tags <my:spacer height="100" /> Decorator <my:infobox type="warning" > <h:message for="selection" /> </my:infobox> Includes <ui:include src="footer.xhtml" /> Composite-Components <my:orderform value="#{order}" showall="true"> <f:validaterequired for="address" /> </my:orderform> 17 Brauchen wir dafür JSF Komponenten? <ol id="ordered_list" class="ui-datalist-data"> <li class="ui-datalist-item"> Chrysler, 1965 </li>... <ol> 18 9
JSF - Implementierungen 2 Implementierungen: Oracle Mojarra (Referenzimplementierung) Apache MyFaces Prinzipiell Austauschbar Servlet-Container: Implementierung typischerweise Teil der Anwendung Freie Wahl der Implementierung Java EE - Application-Server: "Full-Stack-Falle" Implementierung zwingend Teil des Auslieferumfangs Dadurch Festlegung auf Implementierung Version Änderung der JSF-Implementierung möglich Konfiguration notwendig Ggf. Auswirkung auf Garantie/Support 19 Vergleich: MyFaces vs Mojarra 1000 900 800 700 600 [ms] 500 400 300 200 100 0 0 200 400 600 800 1000 1200 1400 # of Components in Tree 20 10
Vergleich: MyFaces vs Mojarra 1000 900 800 700 600 [ms] 500 400 300 200 100 0 0 200 400 600 800 1000 1200 1400 # of Components in Tree 21 Fazit Vergleichsstudie Die Anzahl der verwendeten JSF-Komponenten auf einer Seite hat direkte Auswirkungen auf die Performance der Anwendung. Dies äußert sich hinsichtlich der Abarbeitungsdauer des Lifecycle. Apache MyFaces durchläuft den JSF-Lifecycle erheblich schneller als Oracle Mojarra. Insbesondere Anwendungen mit großen Komponentenbäumen würden somit von einem Umstieg von Mojarra auf MyFaces profitieren. Apache MyFaces bietet unter Berücksichtigung aller untersuchten Aspekte ein gleichwertiges oder besseres Verhalten als die Referenzimplementierung Oracle Mojarra. Durch den beobachteten linearen Anstieg der Abarbeitungsdauer des JSF-Lifecycles ermöglicht MyFaces eine verlässlichere Skalierung der zu erwartenden Laufzeiten. 22 11
Fazit Vergleichsstudie Die Anzahl der verwendeten JSF-Komponenten auf einer Seite hat direkte Auswirkungen auf die Performance der Anwendung. Dies äußert sich hinsichtlich der Abarbeitungsdauer des Lifecycle. Apache MyFaces durchläuft den JSF-Lifecycle erheblich schneller als Oracle Mojarra. Insbesondere Anwendungen mit großen Komponentenbäumen würden somit von einem Umstieg von Mojarra auf MyFaces profitieren. Apache MyFaces bietet unter Berücksichtigung aller untersuchten Aspekte ein gleichwertiges oder besseres Verhalten als die Referenzimplementierung Oracle Mojarra. Durch den beobachteten linearen Anstieg der Abarbeitungsdauer des JSF-Lifecycles ermöglicht MyFaces eine verlässlichere Skalierung der zu erwartenden Laufzeiten. 23 bit.ly/myfaces-vs-mojarra 24 12
Welt-Weites-Warten Browser Servlet-Container GET /index.jsf JSF-Lifecycle RestoreView Render Response GET stylesheet.css Resource Loading: Packing GET script.js GET logo.png 25 JSF - Resource Handling Organisation in WebContent/resources: Rendering: Deklaration: <h:head> <h:outputstylesheet library="css" name="styleb.css" /> <h:outputscript library="js" name="scriptc.js" target="head" /> </h:head> <link rel="stylesheet" href="/myapp/javax.faces.resource/styleb.css.jsf?ln=css"> <script src="/myapp/javax.faces.resource/scriptc.js.jsf?ln=js"> </script> 26 13
Resource Packing Aggregation Resource Packing Minification 27 Resource-Packing: Massnahmen Umsetzung: Build-Prozess Maven Ant Framework Jawr Problem: Links im gerenderten Dokument müssen auf andere Quelle verweisen <link rel="stylesheet" href="/myapp/javax.faces.resource/stylea.css.jsf?ln=css"> <link rel="stylesheet" href="/myapp/javax.faces.resource/styleb.css.jsf?ln=css"> <script src="/myapp/javax.faces.resource/scripta.js.jsf?ln=js"> </script> <script src="/myapp/javax.faces.resource/scriptb.js.jsf?ln=js"> </script> <script src="/myapp/javax.faces.resource/jquery- 1.9.1.min.js.jsf?ln=js"></script> <link rel="stylesheet" href="/myapp/resources/packed.css"> <script src="/myapp/resources/packed.js"></script> 28 14
JSF - Resource Handler Verantwortlich für De/Encoding von Resourcen Liefert Ressource anhand Library und Resourcename Behandelt Resource Requests 29 OmniFaces - CombinedResourceHandler faces-config.xml: <application> <resource-handler> org.omnifaces.resourcehandler.combinedresourcehandler </resource-handler> </application> 30 15
Resource Packing: Problem scripta.js (<1kB) view1.xhtml jquery.js (~91 kb) view2.xhtml scriptc.js (<1kB) 31 Resource Packing: Problem Ungepackt: Requests 9 of 12 3 from Cache 97,1 kb transferred 32 16
Resource Packing: Problem Ungepackt: Requests 9 of12 3 from Cache 97,1 kb transferred Gepackt: Requests 6 of 6 0 from Cache 186,9 kb transferred 33 Resource Packing: Problem Lösung: Caching - Strategie 34 17
Resource Packing Caching Strategie jquery.js [from Cache] view1.xhtml a1.js a2.js view2.xhtml b1.js b2.js 35 OmniFaces - CombinedResourceHandler Ressourcen vom Packing ausschliessen: view.xhtml: <!-- Packed Ressources --> <h:outputscript library="js" name="scriptb.js" target="head" /> <h:outputscript library="js" name="scriptc.js" target="head" /> <!-- Excluded from packing --> <h:outputscript library="js" name="jquery-1.9.1.min.js"/> 36 18
OmniFaces: CombinedResourceHandler Ressourcen vom Packing ausschliessen: web.xml: <context-param> <param-name> org.omnifaces.combined_resource_handler_excluded_resources </param-name> <param-value> javax.faces:jsf.js </param-value> </context-param> 37 OmniFaces: CombinedResourceHandler Ressourcen unterdrücken: web.xml: <context-param> <param-name> org.omnifaces.combined_resource_handler_suppressed_resources </param-name> <param-value> primefaces:primefaces.css </param-value> </context-param> 38 19
Welt-Weites-Warten Browser Servlet-Container GET /index.jsf JSF-Lifecycle RestoreView Render Response GET stylesheet.css Resource Loading: Caching GET script.js GET logo.png 39 Caching- Response Header Production-Stage: HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Expires: Thu, 11 Apr 2013 13:51:12 GMT Last-Modified: Wed, 03 Apr 2013 08:52:01 GMT Content-Type: application/javascript Content-Length: 176 Date: Thu, 04 Apr 2013 13:51:12 GMT 40 20
JSF - Resource Handling JSF Resourcehandling unterstützt Versionierung Standardmässig wird Ressource mit höchster Versionsnummer ausgeliefert Angabe von Version möglich, aber <h:outputscript library="js" name="1_0/scripta.js" target="head" /> Mojarra: erlaubt MyFaces: Warnung: Resource referenced by resourcename 1_0/scriptA.js and libraryname js not found in call to ResourceHandler.createResource. It will be silenty ignored. 41 Response Header anpassen Servlet-Filter geht immer, unabhängig von JSF JSF: 42 21
Welt-Weites-Warten Browser Servlet-Container GET /index.jsf JSF-Lifecycle RestoreView Render Response GET stylesheet.css Resource Loading: Auslagern GET script.js GET logo.png 43 Statische Ressourcen auslagern http://www.oio.de http://static.oio.de Apache httpd 44 22
CDN Content Delivery Network 45 CDN - Vorteile Transfer von statischen Ressourcen schont Application Server Unternehmensnetzwerk Erzeugt (vermutlich) geringere Kosten ab 0,12 $ / GB und Beispiel $0,0090 / 10.000 Requests CDN übernimmt Caching Load-Balancing Skalierung 46 23
JSF und CDN Deployment Extra-Step Maven Ant JSF <link rel="stylesheet" href="/myapp/javax.faces.resource/stylea.css.jsf?ln=css"> <link rel="stylesheet" href="http://mycdn.com/oio/myapp/stylea.css"> 47 JSF Resource Handler 48 24
OmniFaces: CDNResourceHandler faces-config.xml: <application> <resource-handler> org.omnifaces.resourcehandler.cdnresourcehandler </resource-handler> </application> web.xml: <context-param> <param-name> org.omnifaces.cdn_resource_handler_urls </param-name> <param-value> js:jquery.js=http://code.jquery.com/jquery.js </param-value> </context-param> 49 OmniFaces: CDNResourceHandler from CDN Packed 50 25
CDN und Caching Response Header: Access-Control-Allow-Origin:* Content-Encoding:gzip Content-Length:32819 Content-Type:application/x-javascript; charset=utf-8 Date:Fri, 05 Apr 2013 14:02:24 GMT Cache-Control:max-age=2592000 Expires:Sun, 05 May 2013 14:02:24 GMT Last-Modified:Tue, 05 Feb 2013 00:56:40 GMT Vary:Accept-Encoding X-Cache:HIT Server:ECS (fcn/41b6) 51 Welt-Weites-Warten Browser Servlet-Container GET /index.jsf JSF-Lifecycle RestoreView Render Response GET stylesheet.css Resource Loading: GZip GET script.js GET logo.png 52 26
Konfiguration - Tomcat Server.xml <Connector port="8080" protocol="http/1.1" connectiontimeout="20000" redirectport="8443" compression="on" compressionminsize="1024" compressablemimetype="text/css,application/javascript" /> 53 Welt-Weites-Warten Browser Servlet-Container GET /index.jsf JSF-Lifecycle JSF Response Time RestoreView Render Response GET stylesheet.css Resource Loading GET script.js GET logo.png 54 27
Fazit Einfluss auf JSF-Performance: Größe des Komponentenbaumes Wahl der Implementierung # Requests statischer Resourcen verringern: Resource Packing Resource Caching Auslagern (CDN / dedicated Webserver) Netzwerk-Latenz verringern: GZip Kompression nutzen Der Browser kann das schon lange Alle Massnahmen lassen sich mit JSF leicht umsetzen Es existieren außerdem hilfreiche Bibliotheken 55?? Fragen??? Orientation Objects GmbH Weinheimer Str. 68 68309 Mannheim www.oio.de info@oio.de?? 28
Folien zum Vortrag Die Folien werden auf unserer Website veröffentlicht http://oio.de/tiny/orientierungspunkt-archiv 57 Kommende Orientierungspunkte JBoss 7 als Plattform für hochverfügbare Anwendungen Freitag, 24. Mai 2013-17:00-18:00 Uhr Über den Tellerrand: Überblick JSF-Bibliotheken und Tools für den praktischen Einsatz Freitag, 28. Juni 2013-16:00-17:00 Uhr 29
Vielen Dank für ihre Aufmerksamkeit! Orientation in Objects GmbH Weinheimer Str. 68 68309 Mannheim www.oio.de info@oio.de 2.2 sec speedup auf Startseite: +15.4% mehr downloads (= 60 Mill. Downloads / Jahr) 13-25% speedup (GZip): -50% Outbound traffic Mozilla Netflix 60 30
Expires Header "The Expires entity-header field gives the date/time after which the response is considered stale." RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 Wird von JSF automatisch gesetzt Production-Stage: 7 Tage Development-Stage: 0 Probleme: Zu kurzer Zeitraum: Ressource wird redundant ausgeliefert Zu langer Zeitraum Client verpasst Update 61 JSF Resource Handling Standardmässig wird Ressource mit höchster Versionsnummer ausgeliefert Versionierung möglich, aber <h:outputscript library="js" name="1_0/scripta.js" target="head" /> Mojarra: erlaubt MyFaces: Warnung: Resource referenced by resourcename 1_0/scriptA.js and libraryname js not found in call to ResourceHandler.createResource. It will be silenty ignored. 62 31
Performance-Studien World-Wide-Wait, Devoxx 2011 Todo Vergleichsstudie der JSF-Implementierungen Oracle Mojarra und Apache MyFaces, OiO 2013 Todo Vergleichsstudie der JSF- Implementierungen Oracle Mojarra und Apache MyFaces 63 Optimierungspunkte Easy Winner 64 32
9,6 % 65 REST!!! 9,6 % 66 33
Restore View Render Response Validation Invoke Application Apply Request Values Update Model 67 Resources Document 68 34
Resources 69 Response Time Network Latency 70 35
Vergleich: MyFaces vs Mojarra 1000 900 800 700 600 [ms] 500 400 300 MyFaces Server Side MyFaces Client Side Mojarra Server Side Mojarra Client Side 200 100 0 0 200 400 600 800 1000 1200 1400 # of Components in Tree 71 36