Recently we faced a performance issue on a Plone site, which has been reported to be slower than expected.
The application, after a migration to a new hardware, has shown to be a bit lazy compared to the expectations.
Because of the weird behaviour and confident on our Plone installation, we assumed a hardware misconfiguration.
But without evidence (numbers in this case), a claim is merely an opinion.
So, to get ride of the problem, we decided to perform multiple load test on different servers, and then compare the results.
Funkload
http://ziade.org/2011/07/27/how-to-stress-test-your-app-using-funkload-part-1
So, let's see how to set a Funkload test within a buildout.
git clone https://github.com/nicolasenno/funkload.buildout cd funkload.buildout
virtualenv --no-site-packages .
. bin/activate
Then the buildout.cfg (download from github):
[buildout] parts = bench-tools gnuplot versions = versions
[bench-tools] recipe = zc.recipe.egg:scripts eggs = docutils funkload tcpwatch initialization = import os os.environ['TCPWATCH'] = "${buildout:bin-directory}/tcpwatch" [gnuplot] recipe = zc.recipe.cmmi url = http://sourceforge.net/projects/gnuplot/files/gnuplot/4.6.2/gnuplot-4.6.2.tar.gz/download configure-options = --bindirThe test=${buildout:directory}/bin
[versions] funkload = 1.16.1
Gnuplot can be installed directly from buildout, as suggested by Alessandro Pisa on his blog post.
import unittest from random import random from funkload.FunkLoadTestCase import FunkLoadTestCase PAGES = (('Homepage', ''), ('path1', 'contacts'), ('path2', 'media'), ) class Site(FunkLoadTestCase): """This test use a configuration file Site.conf.""" def setUp(self): """Setting up test.""" self.server_url = self.conf_get('main', 'url') def test_app(self): ''' site path ''' server_url = self.server_url for title, page in PAGES: url = "/".join((server_url, page)) self.get(url, description='Get %s' % title)
Then we can use a Makefile to automate the launch process:
LOG_HOME := var/funkload/log REPORT_HOME := var/funkload/data ifdef URL FLOPS = -u $(URL) $(EXT) else FLOPS = $(EXT) endif ifdef REPORT_HOME REPORT = $(REPORT_HOME) else REPORT = report endif all: test test: start test-app bench: start bench-app start: mkdir -p $(REPORT) $(LOG_HOME) test-app: fl-run-test -d --debug-level=3 --simple-fetch site_test.py Site.test_app $(FLOPS) bench-app: fl-run-bench --simple-fetch site_test.py Site.test_app -c 1:5:10:15:20:30:40:50 -D 45 -m 0.1 -M .5 -s 1 $(FLOPS) fl-build-report $(LOG_HOME)/site-bench.xml --html -o $(REPORT) clean:
If you prefer, as an improvement, you can generate this file within the buildout itself.
Take a look to collective.recipe.template for more information.
Here we are!
A couple of shell commands and you will be ready to run the test.
From your buildout directory, type:
make test make test URL=http://override-url/ make bench
At this point a full report will be ready in "{buildout dir}/var/funkload/data" (path depends on your configuration).
Conclusion
As you can see install and run a Funkload load test it's just matter of few steps.
Thanks to it, we have been able to prove our thesis with numbers.
I think it's not a bad idea add it into my checklist of things to do for every site deployment. It could become useful in many other cases.
Recommended reading
http://blog.redturtle.it/how-to-write-funkload-test-in-few-minutes
http://www.martinaspeli.net/articles/tools-for-a-successful-plone-project