This post is a performance audit of the “spring-petclinic” sample application provided by VMWare/SpringSource as a demonstration of the latest Spring features and configurations.
We are going to do a step-by-step audit of the application, and show:
For doing this audit, we will use our own fork of the project, which is located at: https://github.com/jdubois/spring-petclinic
As this tuning is a bit long, we have split it into 5 parts, which we will post every day this week:
Many thanks to:
First of all, we have configured the application to be in “production” mode:
We’ve created a JMeter test, which is available here.
We have run this test a first time, with the “POST new visit” step activated, in order to create 10 visits per pet. This means running this test with 10 threads, doing 13 loops each (as there are 13 pets). The “POST new visit” step was then disabled: the application does not paginate visits, so doing inserts will just break it down really quickly.
As visits are the main objects that are being created in the application, they should have been paginated, or there should be at least a limit on the dataset that is returned. On the other hand, it would be really strange that a user has a pet that goes 1000 times to the vet, so this would not be a realistic test case.
That’s why we have decided to limit this test to 10 visits per pet: this is important, as this will have an impact in the future tests.
We have have then run the test normally (using “mvn clean tomcat7:run“), with a 2011 Macbook Pro, with 500 concurrent users each doing the test 10 times.
It is also important to mention that:
We have also run those tests on several other computers, with the same results (proportionally, some having more CPU power than the others).
The first results are as follow: the application quickly goes up to 285 requests per second (req/sec), then slows down and throws “java.lang.OutOfMemoryError: Java heap space” errors after nearly 700 users. We then have lots of HTTP errors, and the application gets so slow it is not usable anymore.
Of course, we can give more memory to the application, so that it can handle our 5000 users. With 1 Gigabytes of heap, the application can handle the load, with a result of 548 req/sec and 0,2% of HTTP errors.
The application cannot handle a lot of load: with 128 MB of RAM, the application starts to fail after 600 simultaneous users, which is a rather small number. Of course, we can give it more RAM to push that limit: we will be able to have more users, but as the GC will have more work, it is likely that the application does not perform very well.
We will see tomorrow, in the next episode of this series, how we started to solve that problem.
[edit]
You can find the other episodes of this series here : part 2, part 3, part 4 and part 5.