Successfully reported this slideshow.
Performance-tuning the «Spring Pet Clinic»
sample application
By Julien Dubois

© 2013 SpringOne 2GX. All rights reserved....
Why have Java developers chosen Spring?
J(2)EE usability

Deployment
Flexibility

DI

Powerful Service
Abstractions

Appli...
Spring
Deploy to Cloud
or on premise

Big,
Fast,
Flexible
Data
GemFire

Core
Model
Web,
Integration,
Batch
Spring Stack
Spring Data

Spring for Apache Hadoop

Redis

HBase

GemFire

JPA

QueryDSL

HDFS

MapReduce

Hive

MongoDB

...
Learn More. Stay Connected.

Talk to us on Twitter: @springcentral
Find session replays on YouTube: spring.io/video
About me
• Julien Dubois
• From Paris, France
• Co-authored «Spring par la pratique» (French
book on Spring)
• Former Spri...
Goals of this presentation
• Make a specific application run faster
• Learn classic issues with Spring Web
applications
• ...
More information on this presentation
• This presentation started with a series of blog posts:
http://blog.ippon.fr/tag/sp...
What’s new since the blog entries?
• Java 7
• I got a brand new MacBook :-)
–Does a SSD really matters?
–Does the new core...
Introducing
the Spring
Pet Clinic
sample
application
10
Do you remember the Sun Java Pet Store?
• Used to explain how you
could build an incredibly
complex application
• On a ver...
The Spring Pet Clinic
• Is here to demonstrate Spring
features and best practices
• Is a very classical MVC-style
applicat...
More information on the Spring Pet Clinic
• Code:
https://github.com/SpringSource/spring-petclinic/
• Short presentation:
...
#1
Putting the
application
in
production

14
Moving to production
• Be as close as possible to a «production environment»
–Remove «debugging» logs [ Code ]
–Use a «rea...
Memory tuning
• We’re running the application from the Maven Tomcat plugin
–Of course Maven takes some resources

• Still ...
#2
Creating a
JMeter test

17
Simulate load
• JMeter will simulate users
–500 users
–In a «realistic» way
• Use a timer
• Check «clear cookies each iter...
Results
• 250 req/sec
• Lots of errors
• Quickly ends with a crash...

19
#3
Profiling

20
Does profiling distort results?
• Short answer : not a lot
–We’ll see this when the application runs better

• We have use...
Choose your weapon
• VisualVM
–Free & lightweight
–Included in the JDK

• JProfiler
–Best tool we’ve used

• YourKit
–Easy...
First culprit : Dandelion
• More specifically, Dandelion module for
DataTables
–https://github.com/dandelion/dandelion-dat...
Second culprit : the HTTP Session
• Using HTTP Sessions can be helpful
–Developer productivity
–Data security

• Going sta...
Going stateless
• Example : the PetController.processUpdateForm() method
–Use Spring MVC REST to get more information from...
Results
• 500 req/sec
• A few errors
• That’s a lot better than before!

26
#4
Tomcat
tuning

27
Tomcat tuning
• This is the easiest step
–Migrate to the latest version of the Tomcat plugin
–Use the new NIO connector
• ...
Results
• 950 req/sec
• No errors
• Victory :-)

29
#5
Removing
locks

30
Locks
• Locks are blocked threads
–Aka «there’s a synchronized somewhere»

• They obviously cause scalability problems
• L...
First culprit : commons DBCP
• Commons DBCP does a lot of synchronization
• We replaced it with Tomcat JDBC
–New JDBC pool...
Second culprit : Webjars
• WebJars are client-side libraries (JQuery, etc...) packaged as Jar
files
–http://www.webjars.or...
Third culprit : the monitoring Aspect
• This aspect was introduced on purpose
• We should simply disable it [ Code ]

34
Results
• 1020 req/sec, still without any error
• Only 10% performance increase

35
#6
JDBC
vs
JPA
36
3 profiles are available
• Do you use Spring profiles?
• Choose between
–JDBC
–JPA
–Spring Data

37
Switch to JPA
• Change the profile in the web.xml file
• The application is a little bit slower
–904 req/sec
–After an ini...
First problem : Memory
• JPA uses more PermGen, and more memory in general than
JDBC
• Let’s boost the application memory
...
Second problem : SQL requests
• Run MySQL Workbench
–With JDBC we had more than 30 000 SQL requests per second
–With JPA w...
#7
Lazy
loading
41
Lazy loading & Open Session In View
• Pet.visits is an EAGER collection
–This is often a bad idea to eagerly fetch collect...
Results
• 1165 req/sec, still without any error
• 10 000 SQL req/sec
• We have beaten the JDBC version!

43
#8
Adding
cache
44
Hibernate Caching
• We have used Ehcache
• We have put Hibernate’s @Cache annotation everywhere
–Owners, Pets, Visits, etc...
Spring caching
• For more complex queries, we used Spring’s cache
abstraction
–Adds a caching aspect around slow methods

...
Results
• 1240 req/sec, still without any
error
• But can we do better?

47
#9
Extreme
testing
48
Extreme testing
• If we look at the JMeter report, we have reached JMeter’s
limits
–Adding more users (=threads) isn’t doi...
Results
• We achieved 3000 req/sec
• Memory stayed stable
–We even let it run until we had 100 000 user sessions

• We had...
Final
notes

51
Does JDK 7 helps?
• Tested the new G1 Garbage Collector
–export MAVEN_OPTS="-XX:MaxPermSize=128m -Xms256m Xmx256m -XX:+Use...
Does the new MacBook Pro helps?
• Compared to my original blog posts, with my old MacBook
– We still have the memory issue...
#1 Put the
application in
production

#5 Remove
locks

#2 Create a
JMeter test

#6 JDBC vs JPA

#3
Profile

#4 Tune the
ap...
Questions
&
Answers
Late question?
@juliendubois

55
Upcoming SlideShare
Loading in …5
×

Performance-tuning the Spring Petclinic sample application

4,581 views

Published on

Speaker: Julien Dubois
This talk is a live version of my blog posts on performance-tuning the Spring Petclinic application: http://blog.ippon.fr/tag/spring-petclinic/
We will talk about JVM locks, Web application performance best practices, JDBC vs JPA, and caching We will see how to use effectively tools such as JMeter, Yourkit and Intellij IDEA to quickly solve performance issues We will also explain the methodology used, so you can follow the same steps on your own applications
In this session we will talk about :
Stress tests
Memory leaks
Garbage Collection
Profiling tools
Application Server tuning
JVM tuning
Locks
JDBC vs JPA
Lazy loading
Caching
And much more !

Published in: Technology
  • Be the first to comment

Performance-tuning the Spring Petclinic sample application

  1. 1. Performance-tuning the «Spring Pet Clinic» sample application By Julien Dubois © 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission.
  2. 2. Why have Java developers chosen Spring? J(2)EE usability Deployment Flexibility DI Powerful Service Abstractions Application Portability AOP Core Model TX Testable, lightweight model for programming
  3. 3. Spring Deploy to Cloud or on premise Big, Fast, Flexible Data GemFire Core Model Web, Integration, Batch
  4. 4. Spring Stack Spring Data Spring for Apache Hadoop Redis HBase GemFire JPA QueryDSL HDFS MapReduce Hive MongoDB Neo4j Solr JDBC Splunk Pig Cascading SI/Batch Google App Eng. AWS Beanstalk Spring Batch Spring Social Spring Integration Twitter Heroku Spring AMQP Spring Web Services Facebook Spring XD Spring Web Flow LinkedIn Cloud Foundry OpenShift Spring Security Spring Security OAuth Spring Framework DI AOP TX JMS JDBC ORM OXM Scheduling MVC REST HATEOAS JMX Testing Caching Profiles Expression JTA JDBC 4.1 JMX 1.0+ Tomcat 5+ GlassFish 2.1+ WebLogic 9+ WebSphere 6.1+ Java EE 1.4+/SE5+ JPA 2.0 JSF 2.0 JSR-250 JSR-330 JSR-303
  5. 5. Learn More. Stay Connected. Talk to us on Twitter: @springcentral Find session replays on YouTube: spring.io/video
  6. 6. About me • Julien Dubois • From Paris, France • Co-authored «Spring par la pratique» (French book on Spring) • Former SpringSource France director • Director of Consulting at Ippon Technologies • Follow me @juliendubois 6
  7. 7. Goals of this presentation • Make a specific application run faster • Learn classic issues with Spring Web applications • Learn our methodology to solve performance issues 7
  8. 8. More information on this presentation • This presentation started with a series of blog posts: http://blog.ippon.fr/tag/spring-petclinic/ • You can run your own tests, every step is cleanly commited on Github: https://github.com/jdubois/spring-petclinic 8
  9. 9. What’s new since the blog entries? • Java 7 • I got a brand new MacBook :-) –Does a SSD really matters? –Does the new core i7 matters? 9
  10. 10. Introducing the Spring Pet Clinic sample application 10
  11. 11. Do you remember the Sun Java Pet Store? • Used to explain how you could build an incredibly complex application • On a very expensive application server • With an horrible-looking result • When your customer only wanted a simple Web app 11
  12. 12. The Spring Pet Clinic • Is here to demonstrate Spring features and best practices • Is a very classical MVC-style application (no REST + funky JS library) • Is still a good excuse to use cute dogs in your presentation 12
  13. 13. More information on the Spring Pet Clinic • Code: https://github.com/SpringSource/spring-petclinic/ • Short presentation: https://speakerdeck.com/michaelisvy/spring-petclinic-sampleapplication 13
  14. 14. #1 Putting the application in production 14
  15. 15. Moving to production • Be as close as possible to a «production environment» –Remove «debugging» logs [ Code ] –Use a «real» database [ Code ] • For this presentation our environment isn’t perfect –Everything runs on the same machine –Even the presentation itself :-) 15
  16. 16. Memory tuning • We’re running the application from the Maven Tomcat plugin –Of course Maven takes some resources • Still the application runs with a small memory footprint –export MAVEN_OPTS="-XX:MaxPermSize=64m -Xms128m Xmx128m" • Why not use more memory? –It’s easier to spot memory problems –We don’t need it (we’re not using a big fat Java EE server!) 16
  17. 17. #2 Creating a JMeter test 17
  18. 18. Simulate load • JMeter will simulate users –500 users –In a «realistic» way • Use a timer • Check «clear cookies each iteration?» 18
  19. 19. Results • 250 req/sec • Lots of errors • Quickly ends with a crash... 19
  20. 20. #3 Profiling 20
  21. 21. Does profiling distort results? • Short answer : not a lot –We’ll see this when the application runs better • We have used JProfiler and VisualVM in production many times –Often caused less trouble than official «production monitoring tools» like HP Diagnostics –Only way to find problems and understand what’s going on –Easy to install 21
  22. 22. Choose your weapon • VisualVM –Free & lightweight –Included in the JDK • JProfiler –Best tool we’ve used • YourKit –Easy to use & cheap 22
  23. 23. First culprit : Dandelion • More specifically, Dandelion module for DataTables –https://github.com/dandelion/dandelion-datatables • Nice & fun JSP taglib for rendering JQuery DataTables –Has a memory leak in this version –Is now corrected (extremely quick response time from the Dandelion team) • So we switched to «plain old JQuery DataTables» [ Code ] 23
  24. 24. Second culprit : the HTTP Session • Using HTTP Sessions can be helpful –Developer productivity –Data security • Going stateless is often better –Uses less RAM –More scalable 24
  25. 25. Going stateless • Example : the PetController.processUpdateForm() method –Use Spring MVC REST to get more information from the URL –Fetch again the missing data • We said more scalability, not more performance (for the moment) • With some work, the whole application can become stateless [ Code ] 25
  26. 26. Results • 500 req/sec • A few errors • That’s a lot better than before! 26
  27. 27. #4 Tomcat tuning 27
  28. 28. Tomcat tuning • This is the easiest step –Migrate to the latest version of the Tomcat plugin –Use the new NIO connector • org.apache.coyote.http11.Http11NioProtocol • [ Code ] 28
  29. 29. Results • 950 req/sec • No errors • Victory :-) 29
  30. 30. #5 Removing locks 30
  31. 31. Locks • Locks are blocked threads –Aka «there’s a synchronized somewhere» • They obviously cause scalability problems • Let’s launch our profiler again! 31
  32. 32. First culprit : commons DBCP • Commons DBCP does a lot of synchronization • We replaced it with Tomcat JDBC –New JDBC pool for Tomcat, for highly concurrent systems • But we have kept the pool size at 8 –So obviously we will still have locks –Making it bigger hinders performance • If the database was on a separate server, we would use a bigger number • The database is always the problem • [ Code ] 32
  33. 33. Second culprit : Webjars • WebJars are client-side libraries (JQuery, etc...) packaged as Jar files –http://www.webjars.org/ –Those libraries are loaded from the classloader • Which does a big lock each time it is accessed • So if you have a lot of libraries this can be a real problem • There are many solutions to this issue –Cache those resources with a proxy server –Use another solution for loading those libraries (Bower ?) –[ Code ] 33
  34. 34. Third culprit : the monitoring Aspect • This aspect was introduced on purpose • We should simply disable it [ Code ] 34
  35. 35. Results • 1020 req/sec, still without any error • Only 10% performance increase 35
  36. 36. #6 JDBC vs JPA 36
  37. 37. 3 profiles are available • Do you use Spring profiles? • Choose between –JDBC –JPA –Spring Data 37
  38. 38. Switch to JPA • Change the profile in the web.xml file • The application is a little bit slower –904 req/sec –After an initial peak, we see the application hanging and then starting again -> looks like a GC issue 38
  39. 39. First problem : Memory • JPA uses more PermGen, and more memory in general than JDBC • Let’s boost the application memory –export MAVEN_OPTS="-XX:MaxPermSize=128m -Xms256m Xmx256m" –1103 req/sec ! Better than JDBC ! • That’s a different result from our original blog entry –Looks like we need more memory with JDK 7... 39
  40. 40. Second problem : SQL requests • Run MySQL Workbench –With JDBC we had more than 30 000 SQL requests per second –With JPA we have 15 000 SQL requests per second • Why isn’t performance better when we have only half as many requests? 40
  41. 41. #7 Lazy loading 41
  42. 42. Lazy loading & Open Session In View • Pet.visits is an EAGER collection –This is often a bad idea to eagerly fetch collections • Let’s configure it with the default, lazy-loaded mode • To prevent the dreaded LazyInitializationException we’ll use the Open Session In View pattern –Not the «perfect» solution, which would require more refactoring –Good enough in this situation, and easy to implement –[ Code ] 42
  43. 43. Results • 1165 req/sec, still without any error • 10 000 SQL req/sec • We have beaten the JDBC version! 43
  44. 44. #8 Adding cache 44
  45. 45. Hibernate Caching • We have used Ehcache • We have put Hibernate’s @Cache annotation everywhere –Owners, Pets, Visits, etc... 45
  46. 46. Spring caching • For more complex queries, we used Spring’s cache abstraction –Adds a caching aspect around slow methods • Allowed us to remove the very slow «LIKE» in JpaOwnerRepositoryImpl.findByLastName() • We could also have used Hibernate’s query cache for the same result • [ Code ] 46
  47. 47. Results • 1240 req/sec, still without any error • But can we do better? 47
  48. 48. #9 Extreme testing 48
  49. 49. Extreme testing • If we look at the JMeter report, we have reached JMeter’s limits –Adding more users (=threads) isn’t doing a big difference • The solution is to do more with the existing threads –Removed the counter –Decreased the ramp-up period to 5 seconds –Run without any listeners (or in command-line) 49
  50. 50. Results • We achieved 3000 req/sec • Memory stayed stable –We even let it run until we had 100 000 user sessions • We had to increase the JDBC pool size to 30 –Still a small number of connexions –Pushing it to 40 decreases performance 50
  51. 51. Final notes 51
  52. 52. Does JDK 7 helps? • Tested the new G1 Garbage Collector –export MAVEN_OPTS="-XX:MaxPermSize=128m -Xms256m Xmx256m -XX:+UseG1GC" –3% to 5% slower –Needs a bigger heap to work correctly –Doesn’t do any miracle 52
  53. 53. Does the new MacBook Pro helps? • Compared to my original blog posts, with my old MacBook – We still have the memory issues (until solved) – We still have the HTTP errors (until solved) – Results are 10% to 20% better until the last, «extreme testing» phase • If you write inefficient code, a faster CPU and a SSD won’t save you 53
  54. 54. #1 Put the application in production #5 Remove locks #2 Create a JMeter test #6 JDBC vs JPA #3 Profile #4 Tune the application server 54 #7 Lazy loading #8 Add cache
  55. 55. Questions & Answers Late question? @juliendubois 55

×