Development

HowToOptimizeSymfonyForHelloWorldBenchmark

You must first sign up to be able to contribute.

I optimized a new hello world project based on symfony 1.0.6 to a level playing field that represents a complete dynamic dispatch cycle. I have disabled facilities for i18n, caching, databases, user security (though I have enabled sessions support), views with helpers. Basically removing all of the reasons you would want to use a framework, to produce a hello world page, yet represent a complete dynamic dispatch cycle.

Most of these facilities are enabled by default and this decreases the base time for a hello world style benchmark. For most web applications these defaults simplify the process of choosing a framework. Unlike other php frameworks, there is no need to glue together the usual pieces you will need for a decent web app. Yet, these features can easily be disable via a few configs if you want to test a hello world page!

Attached is the project I used and the benchmarks. Big improvements from symfony default based on a few quick tests. If there is anything I turned off that you feel is unfair, please let me know. I have tried to be as unbiased (fair and accurate) as possible in producing just a hello world page without all the framework extras.

There are two hello world tests, one with full view rendering (view configuration: meta, stylesheets, js, layout partial/component processing, loading of helpers, complete template rendering, etc) and one that just renders text, like hello world. Attached are some quick results for both.

urls:

/ -> /helloworld/faster

/helloworld/faster /helloworld/slower

That apache config I used is a slightly optimized config for apache2 on my mac; you can disregard. Also, fyi: apache2/php 5.2.3 with apc (and xdebug) enabled.

How to make an ideal symfony hello world test:

mkdir helloworld
cd helloworld/
mkdir -p lib/vendor
cd lib/vendor
svn export http://svn.symfony-project.com/branches/1.0 symfony
cd ../../
php lib/vendor/symfony/data/bin/symfony init-project helloworld
./symfony init-app helloworld
./symfony init-module helloworld helloworld
./symfony cc

if you move project from original starting point, edit config.php to make paths to symfony adaptable:

// symfony directories

$sf_symfony_root_dir = dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'symfony';

$sf_symfony_lib_dir  = $sf_symfony_root_dir.DIRECTORY_SEPARATOR.'lib';
$sf_symfony_data_dir = $sf_symfony_root_dir.DIRECTORY_SEPARATOR.'data';

[setup apache, link apache config to config/apache.conf, restart]

see: http://www.symfony-project.com/book/1_0/03-Running-Symfony

I used the following:

AddDefaultCharset utf-8
MaxRequestsPerChild 3600

<VirtualHost *>
  ServerName sfperformance.com
  DocumentRoot "/opt/local/apache2/htdocs/sfperformance/web"
  DirectoryIndex index.php

  LogLevel notice
  ErrorLog /opt/local/apache2/htdocs/sfperformance/log/error.log
  CustomLog /opt/local/apache2/htdocs/sfperformance/log/access.log combined

  Options +FollowSymLinks +ExecCGI

  FileETag None

  DeflateFilterNote ratio
  AddOutputFilterByType DEFLATE text/plain text/html application/xhtml+xml text/xml application/xml application/x-javascript text/javascript text/css

  <Location />
    Header append Vary User-Agent env=!dont-vary
  </Location>

  # symfony framework assets
  Alias   /sf                       /opt/local/apache2/htdocs/sfperformance/lib/vendor/symfony/data/web/sf

  <Directory "/opt/local/apache2/htdocs/sfperformance/web">
    AllowOverride None

    Order allow,deny
    Allow from All

    php_admin_value realpath_cache_size 1024K
    php_admin_value realpath_cache_ttl 3600
    php_admin_value memory_limit 32M
    php_admin_value post_max_size 32M
    php_admin_value file_uploads 1
    php_admin_value upload_max_filesize 32M

    ExpiresActive On
    ExpiresDefault A86400
    ExpiresByType text/javascript A2592000
    ExpiresByType application/x-javascript A2592000
    ExpiresByType text/css A2592000
    ExpiresByType image/x-icon A2592000
    ExpiresByType image/gif A604800
    ExpiresByType image/png A604800
    ExpiresByType image/jpeg A604800
    ExpiresByType text/plain A604800
    ExpiresByType application/x-shockwave-flash A604800
    ExpiresByType video/x-flv A604800
    ExpiresByType application/pdf A604800
    ExpiresByType text/html A900

    RewriteEngine On

    RewriteCond %{REQUEST_URI} \..+$
    RewriteRule .* - [L]

    RewriteCond %{REQUEST_FILENAME} !-f

    # no, so we redirect to our front web controller
    RewriteRule ^(.*)$ index.php [QSA,L]

    # big crash from our front web controller
    ErrorDocument 500 "<h2>Application error</h2>symfony application failed to start properly"

  </Directory>
</VirtualHost>


Edit helloworld/apps/helloworld/config/settings.yml:

change the following settings for prod environment:

> all:
>   .actions:
>     default_module:         helloworld      # Default module and action to be called when
>     default_action:         index     # A routing rule doesn't set it
>     #  Optional features. Deactivating unused features boosts performance a bit.
>     use_database:           off    #  Enable database manager. Set to off if you don't use a database.
>     use_security:           off    #  Enable security features (login and credentials). Set to off for public applications.
>     use_flash:              off    #  Enable flash parameter feature. Set to off if you never use the set_flash() method in actions.
>     i18n:                   off    # Enable interface translation. Set to off if your application should not be translated.
>     check_symfony_version:  off    # Enable check of symfony version for every request. Set to on to have symfony clear the cache automatically when the framework is upgraded. Set to off if you always clear the cache after an upgrade.
>     use_process_cache:      on     #  Enable symfony optimizations based on PHP accelerators. Set to off for tests or when you have enabled a PHP accelerator in your server but don't want symfony to use it internally.
>     compressed:             off    # Enable PHP response compression. Set to on to compress the outgoing HTML via the PHP handler.
>     check_lock:             off    # Enable the application lock system triggered by the clear-cache and disable tasks. Set to on to
>     escaping_strategy:      off    #  Determines how variables are made available to templates. Accepted values: bc, both, on, off. 
>     no_script_name:         on      # Enable the front controller name in generated URLs
>     cache:                  off       # Enable the template cache
>     etag:                   off       #  Enable etag handling
>     web_debug:              off       # Enable the web debug toolbar
>     #  Helpers included in all templates by default
>     standard_helpers:       []
> 
>     #  ORM
>     orm:                    off


for added boost since we only want to test a complete dynamic dispatch cycle:

edit helloworld/apps/helloworld/config/filters.yml, to disable cache, security, debug, flashes, and the addition of common view elements via filters:

> rendering: ~
> execution: ~
> 
> web_debug:
>   enabled: off
> 
> security:
>   enabled: off
>
> cache:
>   enabled: off
> 
> common:
>   enabled: off
> 
> flash:
>   enabled: off


edit helloworld/apps/helloworld/config/factories.yml, uncomment defaults and disable symfony sessions from auto starting:

> all:
>   user:
>     class: myUser
> 
>   storage:
>     class: sfSessionStorage
>     param:
>       auto_start:   off

edit helloworld/apps/helloworld/lib/myUser.class.php and change:

< class myUser extends sfBasicSecurityUser
---
> class myUser extends sfUser

This will disable basic user authentication and credential management.

Since we have disabled output escaping we need to modify the default template:

helloworld/apps/helloworld/templates/layout.php

< <?php echo $sf_data->getRaw('sf_content') ?>
---
> <?php echo $sf_content; ?>

add hello world actions for testing:

edit helloworld/apps/helloworld/modules/helloworld/actions.class.php, add:

class helloworldActions extends sfActions
{
  /**
   * Executes index action
   *
   */
  public function executeIndex()
  {
    return $this->executeFaster();
  }

  public function executeFaster()
  {
    return $this->renderText('hello world');
  }

  public function executeSlower()
  {
    return sfView::SUCCESS;
  }
}

add a template for full view comparison:

edit helloworld/apps/helloworld/modules/helloworld/templates/slowerSuccess.php, add:

hello world!

Add some routes for our actions:

edit helloworld/apps/helloworld/config/routing.yml

> 
4c12
<   param: { module: default, action: index }
---
>   param: { module: helloworld, action: index }

Clear cache:

./symfony cc

Now we have disabled all of the optional components of symfony so that it is only loading and using core libraries, not any extras. If you do this on a mac book pro with apache2 / php5.2.3 / apc / xdebug, for the fast hello world action you can get at least 200qps. even faster without xdebug active.

Results my tests:

$ ab -c 50 -t 90 http://sfperformance.com/

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking sfperformance.com (be patient)
Completed 5000 requests
Completed 10000 requests
Completed 15000 requests
Completed 20000 requests
Finished 20252 requests


Server Software:        Apache/2.2.4
Server Hostname:        sfperformance.com
Server Port:            80

Document Path:          /
Document Length:        11 bytes

Concurrency Level:      50
Time taken for tests:   90.127642 seconds
Complete requests:      20252
Failed requests:        0
Write errors:           0
Total transferred:      8198372 bytes
HTML transferred:       223223 bytes
Requests per second:    224.70 [#/sec] (mean)
Time per request:       222.515 [ms] (mean)
Time per request:       4.450 [ms] (mean, across all concurrent requests)
Transfer rate:          88.83 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   41  42.2     30     196
Processing:     8  178 129.6    153    1413
Waiting:        0  158 129.2    126    1277
Total:          8  220 131.1    190    1413

Percentage of the requests served within a certain time (ms)
  50%    190
  66%    237
  75%    276
  80%    310
  90%    399
  95%    478
  98%    577
  99%    651
 100%   1413 (longest request)

$ ab -c 15 -t 10 http://sfperformance.com/

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking sfperformance.com (be patient)
Finished 2309 requests


Server Software:        Apache/2.2.4
Server Hostname:        sfperformance.com
Server Port:            80

Document Path:          /
Document Length:        11 bytes

Concurrency Level:      15
Time taken for tests:   10.6774 seconds
Complete requests:      2309
Failed requests:        0
Write errors:           0
Total transferred:      934452 bytes
HTML transferred:       25443 bytes
Requests per second:    '''230.74''' [#/sec] (mean)
Time per request:       65.007 [ms] (mean)
Time per request:       4.334 [ms] (mean, across all concurrent requests)
Transfer rate:          91.14 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   4.1      0      33
Processing:     7   60 135.5     16     882
Waiting:        0   56 131.9     14     880
Total:          7   62 135.5     17     882

Percentage of the requests served within a certain time (ms)
  50%     17
  66%     24
  75%     31
  80%     34
  90%    204
  95%    417
  98%    544
  99%    638
 100%    882 (longest request)

$ ab http://sfperformance.com/

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking sfperformance.com (be patient).....done


Server Software:        Apache/2.2.4
Server Hostname:        sfperformance.com
Server Port:            80

Document Path:          /
Document Length:        11 bytes

Concurrency Level:      1
Time taken for tests:   0.9093 seconds
Complete requests:      1
Failed requests:        0
Write errors:           0
Total transferred:      404 bytes
HTML transferred:       11 bytes
Requests per second:    109.97 [#/sec] (mean)
Time per request:       '''9.093''' [ms] (mean)
Time per request:       9.093 [ms] (mean, across all concurrent requests)
Transfer rate:          0.00 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     8    8   0.0      8       8
Waiting:        8    8   0.0      8       8
Total:          8    8   0.0      8       8

$ ab -c 50 -t 90 http://sfperformance.com/helloworld/slower

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking sfperformance.com (be patient)
Completed 5000 requests
Completed 10000 requests
Finished 12856 requests


Server Software:        Apache/2.2.4
Server Hostname:        sfperformance.com
Server Port:            80

Document Path:          /helloworld/slower
Document Length:        591 bytes

Concurrency Level:      50
Time taken for tests:   90.57437 seconds
Complete requests:      12856
Failed requests:        0
Write errors:           0
Total transferred:      12663160 bytes
HTML transferred:       7597896 bytes
Requests per second:    142.75 [#/sec] (mean)
Time per request:       350.254 [ms] (mean)
Time per request:       7.005 [ms] (mean, across all concurrent requests)
Transfer rate:          137.31 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   20  29.5      4     194
Processing:    12  327 226.1    330    1543
Waiting:        0  317 227.2    320    1540
Total:         12  348 228.8    345    1543

Percentage of the requests served within a certain time (ms)
  50%    345
  66%    462
  75%    513
  80%    549
  90%    650
  95%    743
  98%    846
  99%    920
 100%   1543 (longest request)

$ ab -c 15 -t 10 http://sfperformance.com/helloworld/slower

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking sfperformance.com (be patient)
Finished 1328 requests


Server Software:        Apache/2.2.4
Server Hostname:        sfperformance.com
Server Port:            80

Document Path:          /helloworld/slower
Document Length:        591 bytes

Concurrency Level:      15
Time taken for tests:   10.6420 seconds
Complete requests:      1328
Failed requests:        0
Write errors:           0
Total transferred:      1309065 bytes
HTML transferred:       785439 bytes
Requests per second:    132.71 [#/sec] (mean)
Time per request:       113.024 [ms] (mean)
Time per request:       7.535 [ms] (mean, across all concurrent requests)
Transfer rate:          127.72 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.3      0       9
Processing:    11  110 128.3     42     628
Waiting:        4  109 127.8     41     628
Total:         11  110 128.3     42     628

Percentage of the requests served within a certain time (ms)
  50%     42
  66%    122
  75%    185
  80%    221
  90%    314
  95%    380
  98%    444
  99%    508
 100%    628 (longest request)

$ ab http://sfperformance.com/helloworld/slower

This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking sfperformance.com (be patient).....done


Server Software:        Apache/2.2.4
Server Hostname:        sfperformance.com
Server Port:            80

Document Path:          /helloworld/slower
Document Length:        591 bytes

Concurrency Level:      1
Time taken for tests:   0.16370 seconds
Complete requests:      1
Failed requests:        0
Write errors:           0
Total transferred:      985 bytes
HTML transferred:       591 bytes
Requests per second:    61.09 [#/sec] (mean)
Time per request:       16.370 [ms] (mean)
Time per request:       16.370 [ms] (mean, across all concurrent requests)
Transfer rate:          0.00 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    16   16   0.0     16      16
Waiting:       15   15   0.0     15      15
Total:         16   16   0.0     16      16

Then again the whole idea of doing this is moot, because you don't use a framework for hello world. You use frameworks to build web apps and at its core symfony is extremely fast, obviously when you add i18n support, caching support, and a bunch of other useful stuff it slowly gets slower.