
ZOPE / CPS / CPSSkins - HIGH PERFORMANCE (v0.5)

Author: Jean-Marc Orliaguet
Last modified : 04-05-10
Changes: security information update for apache proxy

Acknowledgements: Thanks to Sbastien Georget for suggesting the 
RAM-cache improvements on CPSSkins.

Description:
This document describes how to achieve high performance content 
delivery on a Zope / CPS / CPSSkins installation.

References:  
Nuxeo CPS ( http://www.nuxeo.org/cps )
CPSSkins ( http://www.medic.chalmers.se/~jmo/CPS )
Caching with mod_proxy ( http://www.zope.org/Members/rbeer/caching ) 


Background:
Advanced content management systems like CPS provide a lot of 
functionality but they also consume a lot of computer power in terms of 
CPU and memory usage. Each page being displayed requires a new 
computation. Using a theme management system  like CPSSkins on top of 
CPS adds a lot of flexibility to it but it also increases computation 
requirements. 

The typical number of requests per second that can be achieved by 
communicating directly to a Zope server are represented in this table:

Platform
Zope / CMF1.3
CPS2
CPS2 + CPSSkins
Requests per second
20
3
1.8


The tests were run on a Mobile Intel(R) Pentium(R) III CPU - M  1333MHz
on Linux using ApacheBench: 
 

# ab -n 20 http://localhost:8080/...


The same page served statically on the Apache web server could easily 
reach 1000 to 2000 requests / second.


One solution to achieve comparable high performance results on a CPS 
site is: 
to let Apache cache some of the documents delivered by the Zope server.
To let the Zope server cache often served objects in the RAM. 

This solution involves the use of 4 main components:

Zope + CMF Caching Policy Manager + Apache mod_proxy (with cache) + 
Zope RAM-Cache manager.


Software used:
Zope 2.6.1 ( http://www.zope.org ) 
Apache 1.3.28 ( http://www.apache.org )
CPS 2.2b2 ( http://www.nuxeo.org ) 
CPSSkins >= 1.9 ( http://www.medic.chalmers.se/~jmo/CPS )


A. Proxy-caching 

The caching proxy stores documents on the Apache server.

a) Install and configure Apache with mod_proxy enabled
b) Install Zope + CPS + CPSSkins
c) In the Apache main configuration section add the following lines:


ProxyRequests On

CacheRoot "/var/www/proxy"
CacheSize 5
CacheGcInterval 4
CacheMaxExpire 24
CacheLastModifiedFactor 0.1
CacheDefaultExpire 1
CacheForceCompletion 100

WARNING 
(from Caching with mod_proxy - http://www.zope.org/Members/rbeer/caching ): 
There is a security problem insofar that if you setup your 
server just like this it will be a public proxy that people can use 
to cover their traces when accessing other websites. To disable 
this behavior you could e.g. add a LocationMatch directive to 
your httpd.conf that denies every request that doesn't start with a slash.

<LocationMatch "^[^/]">
Deny from all
</LocationMatch>


The cache root directory must be writable by the Apache process 
(usually 'nobody' or 'apache' )

d) In the Apache virtual host configuration section add the following 
lines to the Virtual Host configuration section.


ProxyPass /cps 
http://localhost:8080/VirtualHostBase/http/localhost:80/cps/VirtualHostR
oot/_vh_cps

ProxyPassReverse 
http://localhost:8080/VirtualHostBase/http/localhost:80/cps/VirtualHostR
oot/_vh_cps  /cps


... provided that the CPS instance is running on 
http://localhost:8080/cps and that the Apache server runs on 
http://localhost:80 
Replace localhost with the actual  server name. 
Remove _vh_... if the site's initial URL is /  

  
e) Add a "Virtual Host Monster" (VHM) at the root of the CPS instance

f) Add a "CMF Caching Policy Manager" at the root of the CPS instance
. with the following values:



Policy ID : 		authenticated
Predicate: 		python:member!=None
Mod. Time: 		content/bobobase_modification_time
Max age (secs): 	0
No-cache?: 		[x]
No-store?: 		[ ]
Must-revalidate?: 	[ ]

Policy ID : 		anonymous
Predicate: 		python:member==None
Mod. Time: 		content/bobobase_modification_time
Max age (secs): 	600
No-cache?: 		[ ]
No-store?: 		[ ]
Must-revalidate?: 	[ ]


This will tell Apache to cache anonymous pages with a lifetime of 600 
seconds (10 minutes) and to never cache authenticated pages (which 
would otherwise constitute a potential security issue)



B. RAM-Caching 

The RAM-cache stores objects in memory on the Zope server.
Objects that are often called can be cached (e.g. Python scripts, DMTL, 
... ).
The method that is most often called in CPSSkins is the 'render()' 
method. It is used to render all UI elements, and the dynamic 
stylesheets.

Installation.

The current version of CPSSkins automatically installs and configures 
the cache manager.

In the theme edition pages, click on the "Cache manager" menu > and 
press [Activate the RAM-cache] to turn it on.




Cacheable elements
Starting from version 1.8o of CPSSkins,  all UI elements can be cached 
on an individual basis. If an element is not displayed as it is 
expected, then deselect the 'Cacheable' option or decrease the cache 
cleanup interval. The stylesheets (styles) are cached by default.






You can also use the cache-manager configuration page to get an 
overview of which Templets will be cached.




Warning: if your site is multilingual, language-dependent Templets 
cannot be cached.

Results:

Proxy-cache:
The typical number of requests per seconds was increased from 2  to 
1000 by using the proxy cache. (see benchmarks below) This is effective 
for anonymous users only.

RAM-cache:
Caching the 'cpsskins_render' method used in CPSSkins greatly improves 
rendering times. This is effective for both anonymous and authenticated 
users.

for the dynamic stylesheets (cpsskins_css/custom.css) improvements are 
by a threefold factor -- from typically 10 rps to 30 rps

pages are rendered three to four times faster (see benchmarks below). 

The hits to misses ratio is typically 10:1



Benchmarks* :
* these are only approximate benchmarks.

Tools: 
BenchmarkTimer ( http://www.zopelabs.com/cookbook/1019080479 )
ApacheBench ( http://www.apache.org )

A) CPS3 + CPSSkins - Without RAM Cache - without Proxy Cache
     
rendering time : 0.49s  (see appendix 1)


B) CPS3 + CPSSkins - With RAM Cache - without Proxy Cache

rendering time : 0.16s (see appendix 2)


C) CPS2 + CPSSkins - Without RAM Cache - with Proxy Cache
/usr/sbin/ab -n 1000 -c 1000 ...

requests per second : 500 (see appendix 3)


APPENDIX 1 - CPS3 + CPSSkins1.8n - Without RAM Cache - without Proxy 
Cache


 Profiling lvl:-1 cpsskins_main_template:
 t       mark       delta t
 0.0000: Start      + 0.0000
 0.0200: CPSSkins: banner START + 0.0200
 0.0300: CPSSkins: banner END + 0.0100
 0.0400: CPSSkins: welcome box START + 0.0100
 0.0700: CPSSkins: welcome box END + 0.0300
 0.0700: CPSSkins: search box START + 0.0000
 0.0800: CPSSkins: search box END + 0.0100
 0.0900: CPSSkins: flags START + 0.0100
 0.1000: CPSSkins: flags END + 0.0100
 0.1100: CPSSkins: Action bar START + 0.0100
 0.1700: CPSSkins: Action bar END + 0.0600
 0.1800: CPSSkins: level1 START + 0.0100
 0.2100: CPSSkins: level1 END + 0.0300
 0.2100: CPSSkins: level2 START + 0.0000
 0.2300: CPSSkins: level2 END + 0.0200
 0.2500: CPSSkins: Boxes 3 START + 0.0200
 0.2800: CPSSkins: Boxes 3 END + 0.0300
 0.2900: CPSSkins: Admin box START + 0.0100
 0.3300: CPSSkins: Admin box END + 0.0400
 0.3300: CPSSkins: box group 0 START + 0.0000
 0.3700: CPSSkins: box group 0 END + 0.0400
 0.3700: CPSSkins: Breadcrumbs START + 0.0000
 0.3800: CPSSkins: Breadcrumbs END + 0.0100
 0.3900: CPSSkins: Main Content START + 0.0100
 0.3900: CPSSkins: Main Content END + 0.0000
 0.4000: CPSSkins: Last modified START + 0.0100
 0.4100: CPSSkins: Last modified END + 0.0100
 0.4100: CPSSkins: Action box START + 0.0000
 0.4400: CPSSkins: Action box END + 0.0300
 0.4400: CPSSkins: Group 2 START + 0.0000
 0.4800: CPSSkins: Group 2 END + 0.0400
 0.4900: Stop       + 0.0100
















APPENDIX 2 - CPS3 + CPSSkins1.8n - With RAM Cache - without Proxy Cache


 Profiling lvl:-1 cpsskins_main_template:
 t       mark       delta t
 0.0000: Start      + 0.0000
 0.0200: CPSSkins: banner START + 0.0200
 0.0200: CPSSkins: banner END + 0.0000
 0.0300: CPSSkins: welcome box START + 0.0100
 0.0300: CPSSkins: welcome box END + 0.0000
 0.0400: CPSSkins: search box START + 0.0100
 0.0400: CPSSkins: search box END + 0.0000
 0.0500: CPSSkins: flags START + 0.0100
 0.0500: CPSSkins: flags END + 0.0000
 0.0600: CPSSkins: Action bar START + 0.0100
 0.0600: CPSSkins: Action bar END + 0.0000
 0.0700: CPSSkins: level1 START + 0.0100
 0.0700: CPSSkins: level1 END + 0.0000
 0.0700: CPSSkins: level2 START + 0.0000
 0.0800: CPSSkins: level2 END + 0.0100
 0.0900: CPSSkins: Boxes 3 START + 0.0100
 0.0900: CPSSkins: Boxes 3 END + 0.0000
 0.1000: CPSSkins: Admin box START + 0.0100
 0.1000: CPSSkins: Admin box END + 0.0000
 0.1000: CPSSkins: box group 0 START + 0.0000
 0.1000: CPSSkins: box group 0 END + 0.0000
 0.1100: CPSSkins: Breadcrumbs START + 0.0100
 0.1100: CPSSkins: Breadcrumbs END + 0.0000
 0.1200: CPSSkins: Main Content START + 0.0100
 0.1200: CPSSkins: Main Content END + 0.0000
 0.1300: CPSSkins: Last modified START + 0.0100
 0.1300: CPSSkins: Last modified END + 0.0000
 0.1400: CPSSkins: Action box START + 0.0100
 0.1400: CPSSkins: Action box END + 0.0000
 0.1500: CPSSkins: Group 2 START + 0.0100
 0.1500: CPSSkins: Group 2 END + 0.0000
 0.1600: Stop       + 0.0100
APPENDIX 3 - CPS2 + CPSSkins - Without RAM Cache - with Proxy Cache
This is ApacheBench, Version 1.3d <$Revision: 1.6 $> apache-1.3
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, 
http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, 
http://www.apache.org/

Benchmarking bell.ita.chalmers.se (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests
Server Software:        Zope/(Zope                                      
   
Server Hostname:        bell.ita.chalmers.se
Server Port:            80

Document Path:          
/lanksida/webapplicationdocument_list?sortby=category
Document Length:        34666 bytes

Concurrency Level:      1000
Time taken for tests:   1.689 seconds
Complete requests:      1000
Failed requests:        0
Broken pipe errors:     0
Total transferred:      35159779 bytes
HTML transferred:       34773239 bytes
Requests per second:    592.07 [#/sec] (mean)
Time per request:       1689.00 [ms] (mean)
Time per request:       1.69 [ms] (mean, across all concurrent requests)
Transfer rate:          20816.92 [Kbytes/sec] received

Connnection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0     4    6.5      1    22
Processing:    29   204   42.6    214   425
Waiting:        8   203   42.6    213   424
Total:         29   208   37.8    215   445

Percentage of the requests served within a certain time (ms)
  50%    215
  66%    217
  75%    218
  80%    219
  90%    222
  95%    234
  98%    239
  99%    245
 100%    445 (last request)
