Blogs / Gaetano Giunta / Benchmarking eZ: memory consumption for the webservice use case

Benchmarking eZ: memory consumption for the webservice use case

Tuesday 01 March 2011 6:16:00 am

  • Currently 5 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

By : Gaetano Giunta

The amount of memory used by the application to render a single page is an important metric to be taken into account when sizing webservers to cope with the desired amount of traffic. In this installment, we explore memory usage by eZ Publish, in the context of a "webservice" page, ie. a page rendering a very simple piece of text in json format. We focus on an aspect outside control of the developer: php files with class definitions.

Sizing servers

The rule of thumb, for a server dedicated to running only Apache, is to start with the installed memory, take away a fixed amount for the OS (eg. 500MB) and divide the rest for the number of concurrent webservers processes expected. For a 4GB server, with 100 processes, that means 35MB per process.

Do remember that if a php page consumes eg. 30MB, and the following requested page only 10MB, Apache will not release to the OS the extra 20MB until the process that served the 1st page is recycled.

This is a good reason for keeping an eye on the MaxRequestperChild parameter to keep your processes refreshing now and then (but not once per minute, or you'll slow don everything in process creation and killing). It is also an excellent reason to install a separate web application for serving static content (eg. nginx), even on the same server, and for doing proper usage of the caches in your eZ Publish applications. It might also be a good idea to have the editorail siteaccess on a separate server, since "editing" pages tend to chew up momery memory than "display" pages.

Things outside of developer's control

Even with the most advanced cache-block technique in place, the number of php classes used by eZ Publish to do its job is outside of the control of the developer. And every parsed php file chews up some memory. What I set out to do here is to measure the minimum number of php files that are loaded by the system, their size on disk, and the memory consumed by php for loading them.

Measurement methodology

A stripped-down eZ Publish 4.5beta1 install was measured:

  • 2 siteaccess
  • english language content only
  • all default content classes and demo content removed
  • all extensions disabled (this means admin2 design cannot be used, as it relies on ezjscore)
  • template translation disabled
  • all ini files set up by the install wizard but not necessary for testing removed
  • homepage is from a content class with a single attribute (text line)

This in order to obtain the lowest possible memory usage.

The autoload.php file was then patched to record the php files loaded and the memory used by php before and after the inclusion. Total memory at the end of script execution was not measured.

All tests were done on windows 32bit, with php 5.3.5. No opcode cache in use.

Results

  • caches emptied in admin interface, 1st load of homepage (using the pagelayout and node template from the "base" design): 19,66 MB ram; 102 php files totaling 3,17MB on disk
  • same with caches primed: 10,22 MB ram; 51 php files totaling 1,69 MB on disk
  • same with a 'clean' pagelayout (ie. only containing module_result): 10,22 MB ram, 47 php files totaling 1,62 MB on disk
  • using a 'clean' pagelayout and a custom module (no content view) that only echoes current time without using a template: 8,91 MB ram, 46 php files totaling 1,37 MB on disk
  • using a jsonrpc service (with the ggwebservices extension) that echoes current time: 6,55 MB ram, 45 php files totaling 1,08MB on disk
  • using the new REST API layer and a json view displaying the current time: 4,45 MB ram, 90 php files

Conclusions

  • the biggest offenders in terms of size/memory used are the eZTemplateCompiler and eZContentObject php classes. If eZP could avoid loading them at all on a page with view caches fully on, almost 2MB of ram would be saved
  • many php classes are brought in even if only one or two of their methods are used. Eg. ezdebugsetting which is always pulled in even with debug off; ezphpcreator; the charset/codec layer
  • a lot of refactoring work would be needed to split off these classes into lighter "stubs". eg. the ezdebug class could be split in one light half-class that is always pulled in, and one heavy half class that is only pulled in when debug is in fact active (the debug-writer part)
  • using a module view that bypasses the template layer by calling eZExecution::cleanExit(); instead of using an empty pagelayout can result in some memory saving
  • the new controller layer implemented in the REST API does much better than what can be obtained via a custom module/view with the current API!