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!

eZ debug

Timing: Jan 18 2025 03:06:23
Script start
Timing: Jan 18 2025 03:06:23
Module start 'content'
Timing: Jan 18 2025 03:06:23
Module end 'content'
Timing: Jan 18 2025 03:06:23
Script end

Main resources:

Total runtime0.1337 sec
Peak memory usage4,096.0000 KB
Database Queries141

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0061 589.4297180.8047
Module start 'content' 0.00610.0051 770.234499.1406
Module end 'content' 0.01120.1224 869.3750536.3203
Script end 0.1336  1,405.6953 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00372.7790200.0002
Check MTime0.00141.0773200.0001
Mysql Total
Database connection0.00070.536310.0007
Mysqli_queries0.094870.92391410.0007
Looping result0.00110.81801390.0000
Template Total0.122191.310.1221
Template load0.00090.651510.0009
Template processing0.121290.666710.1212
Override
Cache load0.00060.447310.0006
Sytem overhead
Fetch class attribute can translate value0.00080.631310.0008
XML
Image XML parsing0.00030.208710.0003
General
dbfile0.00221.6767200.0001
String conversion0.00000.004330.0000
Note: percentages do not add up to 100% because some accumulators overlap

CSS/JS files loaded with "ezjscPacker" during request:

CacheTypePacklevelSourceFiles
CSS0extension/community/design/community/stylesheets/ext/jquery.autocomplete.css
extension/community_design/design/suncana/stylesheets/scrollbars.css
extension/community_design/design/suncana/stylesheets/tabs.css
extension/community_design/design/suncana/stylesheets/roadmap.css
extension/community_design/design/suncana/stylesheets/content.css
extension/community_design/design/suncana/stylesheets/star-rating.css
extension/community_design/design/suncana/stylesheets/syntax_and_custom_tags.css
extension/community_design/design/suncana/stylesheets/buttons.css
extension/community_design/design/suncana/stylesheets/tweetbox.css
extension/community_design/design/suncana/stylesheets/jquery.fancybox-1.3.4.css
extension/bcsmoothgallery/design/standard/stylesheets/magnific-popup.css
extension/sevenx/design/simple/stylesheets/star_rating.css
extension/sevenx/design/simple/stylesheets/libs/fontawesome/css/all.min.css
extension/sevenx/design/simple/stylesheets/main.v02.css
extension/sevenx/design/simple/stylesheets/main.v02.res.css
JS0extension/ezjscore/design/standard/lib/yui/3.17.2/build/yui/yui-min.js
extension/ezjscore/design/standard/javascript/jquery-3.7.0.min.js
extension/community_design/design/suncana/javascript/jquery.ui.core.min.js
extension/community_design/design/suncana/javascript/jquery.ui.widget.min.js
extension/community_design/design/suncana/javascript/jquery.easing.1.3.js
extension/community_design/design/suncana/javascript/jquery.ui.tabs.js
extension/community_design/design/suncana/javascript/jquery.hoverIntent.min.js
extension/community_design/design/suncana/javascript/jquery.popmenu.js
extension/community_design/design/suncana/javascript/jScrollPane.js
extension/community_design/design/suncana/javascript/jquery.mousewheel.js
extension/community_design/design/suncana/javascript/jquery.cycle.all.js
extension/sevenx/design/simple/javascript/jquery.scrollTo.js
extension/community_design/design/suncana/javascript/jquery.cookie.js
extension/community_design/design/suncana/javascript/ezstarrating_jquery.js
extension/community_design/design/suncana/javascript/jquery.initboxes.js
extension/community_design/design/suncana/javascript/app.js
extension/community_design/design/suncana/javascript/twitterwidget.js
extension/community_design/design/suncana/javascript/community.js
extension/community_design/design/suncana/javascript/roadmap.js
extension/community_design/design/suncana/javascript/ez.js
extension/community_design/design/suncana/javascript/ezshareevents.js
extension/sevenx/design/simple/javascript/main.js

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1pagelayout.tpl<No override>extension/sevenx/design/simple/templates/pagelayout.tplEdit templateOverride template
 Number of times templates used: 1
 Number of unique templates used: 1

Time used to render debug report: 0.0001 secs