The blog of COil: PHP, PEAR, symfony1, Symfony2 & iWeb2.0+

Strangebuzz...?

» Collapse all «

symfony

All Symfony related stuff.

Entries feed - Comments feed

Thursday 21 February 2013

Twig C extension benchmark

Hi Symfonians,

Long time since my last post ! But it's mainly because I actually have a lot of work with Symfony2 projects. One of my current task is to optimize the performances of a Symfony2.0.x project. I was curious to test the Twig C extension to check if there was a real improvement before using it in our production environment. Here we go:

I will not describe the installation as it is very easy, just follow the official documentation. When the extension is correctly installed you have a new Twig entry in your phpinfo():


The benchmark


To test the extension, I choose the most complex page of the site (complex at the Twig level):

  • Renders a tree of about 500 checkboxes
  • Recursive include calls are made inside the templates
  • Widget rendering does not use the Symfony2 form helpers


The main template:

(Called 6 times with different data)

The recursive Twig template _group_tree.html.twig:

PS: Note here that we didn't used here a native Symfony2 form, because the rendering (bind + renderering) was taking about 5 seconds...

Test conditions:

  • Symfony 2.0.22, of course the production environment is used for the test.
  • PHP 5.3.2-1ubuntu4.18 with Suhosin-Patch (cli) (built: Sep 12 2012 19:12:47)
  • php app/check.php, no warning or error, APC is enabled with an APC autoloader.


Results without the extension:

  • 1000 iterations
  • Apache was restarted and Symfony2 cache was cleared between each test

The following results are the second run because the 1st run has to rebuild the Symfony cache.

[10:39:54] coil@ubuntu:~/Webdev$ ab -n 1000 http://dev.project.com/search
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking dev.project.com (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
Completed 1000 requests
Finished 1000 requests

Server Software:        Apache/2.2.14
Server Hostname:        dev.project.com
Server Port:            80

Document Path:          /search
Document Length:        197192 bytes

Concurrency Level:      1
Time taken for tests:   99.232 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      197742000 bytes
HTML transferred:       197192000 bytes
Requests per second:    10.08 [#/sec] (mean)
Time per request:       99.232 [ms] (mean)
Time per request:       99.232 [ms] (mean, across all concurrent requests)
Transfer rate:          1946.03 [Kbytes/sec] received

Connection Times (ms)
	      min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    95   99   4.4     98     190
Waiting:       92   96   4.2     95     187
Total:         95   99   4.4     98     190

Percentage of the requests served within a certain time (ms)
  50%     98
  66%    101
  75%    102
  80%    102
  90%    103
  95%    104
  98%    108
  99%    110
 100%    190 (longest request)


Results with the extension enabled:


[10:36:34] coil@ubuntu:~/Webdev$ ab -n 1000 http://dev.project.com/search
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking dev.project.com (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
Completed 1000 requests
Finished 1000 requests

Server Software:        Apache/2.2.14
Server Hostname:        dev.project.com
Server Port:            80

Document Path:          /search
Document Length:        197192 bytes

Concurrency Level:      1
Time taken for tests:   84.887 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      197742000 bytes
HTML transferred:       197192000 bytes
Requests per second:    11.78 [#/sec] (mean)
Time per request:       84.887 [ms] (mean)
Time per request:       84.887 [ms] (mean, across all concurrent requests)
Transfer rate:          2274.87 [Kbytes/sec] received

Connection Times (ms)
	      min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    81   85   2.9     84     127
Waiting:       78   82   2.7     81     124
Total:         81   85   2.9     84     127

Percentage of the requests served within a certain time (ms)
  50%     84
  66%     86
  75%     87
  80%     87
  90%     88
  95%     89
  98%     91
  99%     94
 100%    127 (longest request)


(I have run the tests several times to check that the results are reliable)

Conclusion


As you can see, it is quiet interesting as the global gain is about 14,5%. I have tested on several smaller templates but the gain was insignificant and less than 1%. (which seems logical)

So the extension can really be helpful on complex templates with a lot of parameters, the more complex the Twig templates are the more gain you will have. (up to 15%)

See you. COil :)


About the extension:


For other Symfony2 performance tricks check out the following resources:


Friday 25 May 2012

[Snippet] Bash script to generate Symfony2 doctrine files

Hi Symfonians ! :)

Here is a very basic bash script to help generate files for a given entity of your database, useful when you don't want to reverse engineer all the tables: (replace MyBundle and MyNamespace by your own values)

./build_entities.sh Product


PS: Note that the filter allow to generate more that one entity. (ex: "Product", "ProductFoo"...)

Saturday 3 March 2012

[Symfony2] Request class mini-cheatsheet

Hi symfonians ! ^^

Considering the following URL:

http://dev.col.com/app_dev.php/my-route?bar=1&foo=bar


Here are the results of the different main public methods of the Symfony\Component\HttpFoundation\Request class about the URL and server analysis: (calls are made inside a basic controller class)

$r = $this->getRequest();
$r->getClientIp()	127.0.0.1
$r->getScriptName()	/app_dev.php
$r->getPathInfo()	/my-route
$r->getBasePath()	''
$r->getBaseUrl()	/app_dev.php
$r->getScheme()		http
$r->getPort()		80
$r->getHttpHost()	dev.col.com
$r->getRequestUri()	/app_dev.php/my-route?bar=1&foo=bar
$r->getUri()		http://dev.col.com/app_dev.php/my-route?bar=1&foo=bar
$r->getUriForPath("/other-path") http://dev.col.com/app_dev.php/other-path
$r->getQueryString()	bar=1&foo=bar
$r->isSecure()		false
$r->getHost()		dev.col.com
$r->getMethod()		GET
$r->isXmlHttpRequest()	false


I have submitted a small PR to the git main Symfony2 repository to have a new function that I need in one of my sf2 projects. If your are interested in this PR, feel free to add a comment :) :

$r->getBaseServerUrl()	http://dev.col.com


It was to avoid the following Twig code:


See you. COil :)

PS: Note that the getBasePath() function returns an empty string as the root of the virtual host is set to the /web folder of the application, for an URL like http://dev.col.com/web/app_dev.php/my-route?bar=1&foo=bar it would return /web.

PS2: If you want real Symfony cheatsheet, check the blog of Andréia Bohner.

PS3: My PR was useful !! :)

Thursday 9 February 2012

Simple bash script to update Symfony2

As you noticed there are frequent maintenance releases of Symfony2, the 2.0.10 version is already out. To avoid doings thing manually I use this simple bash script to make the update: (It works with a Symfony2 standard edition). To use it, just launch the script at the root of your project: (be careful as it will delete your vendor directory)

./update_symfony 2.0.10

The bash script:


See you. :)

Other related posts;

Saturday 28 January 2012

Load fixtures with Symfony2 and YAML files

Hi Symfonians ! :)

I am actually spending a lot of time on testing Symfony2. When building an application, one of the first thing you will have to do is to insert initial data, also called fixtures, so you can use and test your application. There is a documentation on the Symfony website about this subject, it uses the DoctrineFixturesBundle.

It works very well, but I wanted to use YAML files "a la symfony1". So I ended up with this simple solution:

The base Loader class:

First, I create a base Loader class that others entities loaders will extend:


The getModelFixtures() function will load the YAML file corresponding to the current entity, the getModelFile() function will have to be implemented by sub-loaders. The class implements the ContainerAwareInterface so we can access the DIC in the loaders.

The Category loader:


The YAML file:

Both jobs and categories YAML files are almost equal to the Jobeet1 tutorial ones.


The loader class:

The getModelFixtures() function retrieves the fixtures for the Category entity and then you just have to iterate over the array. At each iteration we add a reference to the entity so it can be used in other loaders. (as a foreign key)

The Job loader:


The YAML file:


The loader class:


Same here, but:

  • For each iteration we retrieve the proper category reference we already built in the Category loader (line 30).
  • In Jobeet1 there was a loop directly in the YAML file in order to add lot of job rows, now we can do this loop in our loader: duplicateLastJob().
  • There is also a special case where we force a value for the expiresAt date field that would be overridden by the Job object life-cycle callbacks otherwise.

I think this a good approach as you have the ease of writing YAML without loosing the possibility to handle complex or edge cases with PHP. You can find the code on github.

See you ! COil :)

PS: This tutorial was tested with Symfony Standard Edition 2.0.9.
PS2: If you have a blog post about fixtures, let me know so I can add it below.

Other posts about fixtures:

Friday 6 January 2012

Extending the Symfony2 session

Hi symfonians ! :)

If you are used to symfony1, you probably noticed that you don't have a myUser class to handle the user session. It's generally useful so you don't have to handle directly with session attributes and you can also have shortcuts. Well it's quiet easy to have such a class in Symfony2:
Declare your own session class as the framework level in your app/config.yml config file:


And now create your own mySession class which extends the default Symfony2 session class:


And your done. :)

PS: The class can be stored in another location, I'm not sure which is the best ?
PS2: The service could also be loaded at the Bundle level.

Saturday 22 October 2011

symfony1 sfToolsPlugin 1-0-0 released

Hi symfonians ! :)

Today I released a new plugin; the sfToolsPlugin , it's probably the smallest one I released as it only has one class and 3 main functions. In fact it contains a class I use to copy in every project I am working on. Sometimes with different names... Bored with this, even it's more a snippet than a plugin, I made the symfony1 plugin so I can call it the same way in every project I am working on and install it as a SVN external.

As the name of this plugin is very generic, feel free to send me your contribution requests for something you feel like it could be in it. ;)


sfToolsPlugin

Wednesday 5 October 2011

symfony1 sfTCPDFPlugin 1-6-3 released

Last week I also released the 1.6.3 version of the sfTCPDFPlugin. It is just of small update to check that it works without problem with the last TCPDF library which is actually at version 5_9_120 (2011-09-22). (Note that the release strategy of this library is very fast with a lot of minor versions). You can check the CHANGELOG here.

sfTCPDFPlugin


PS: There is now more than 100 registered users for this plugin ! :)

See you. COil :)

Thursday 29 September 2011

symfony1 sfTaskLoggerPlugin 1-0-3 released

Last week I released the 1.0.3 version of the sfTaskLoggerPlugin. It corrects several bugs and adds several features. The main improvement of this version is that it is bundled with a fully customized Doctrine admin generator module in order to manage and check the tasks launched by the plugin. You can check the changelog here. I hope that with this version the plugin will overtake the huge number of registered users of 8 ! :D

sfTaskLoggerPlugin


PS : Note that there is a bug in the partial that shows the task total length, use the svn trunk (which is actually stable et revision 33110) if you want to correct it.

See you. COil :)

Monday 11 April 2011

sfMyPlugins, 2 years later

Well, 2 years have passed since my post: "Writing symfony plugins is great... maintaining them is better !". I followed my own advices and all my plugins where updated for symfony 1.4 which will be the last major version of the 1.x branch. Now let's see how things evolved since 2 years:

sfDB4toPropelPlugin

sfDB4toPropelPlugin
  • User counts: 11 (+8 users since 12 apr 2009)
  • Available for: sf 1.4, 1.3, 1.2
  • Users feedbacks: 0
  • I like and use the sfDB4toPropelPlugin !
  • Want the Symfony2 bundle ? Send me an email ! ^^


I must admit I don't use this plugin any more. Because most of people are using Doctrine as it is the recommended ORM for symfony now. But it can be useful for a small project. I didn't had feedbacks about it, it just "do the job" as it should. (It's very stable because it was extensively used for 2 big 1.0 projects)

sfLightboxPlugin

sfLightboxPlugin
  • User counts: 55 (+39 users since 12 apr 2009)
  • Available for: sf 1.4, 1.3, 1.2, 1.1, 1.0
  • Users feedbacks: 1
  • I like and use the sfLightboxPlugin !


It's probably the most useless of my plugin, but I think it is used because it is well documented, very easy to use and available for all symfony major versions.

sfTCPDFPlugin

sfTCPDFPlugin
  • User counts: 93 (+84 users since 12 apr 2009)
  • Available for: 1.4, 1.3, 1.2
  • Users feedbacks: 4
  • I like and use the sfTCPDFPlugin !


This plugin had a very nice users boost since its creation, its my most popular plugin. Therefore I suppose that it works quiet well. :) It allows to avoid dealing with the unfriendly TCPDF constants with a help of a multi-configurations YAML file.

sfTaskLoggerPlugin

sfTaskLoggerPlugin
  • User counts: 8
  • Available for: 1.4, 1.3, 1.2, 1.1
  • Users feedbacks: 3
  • I like and use the sfTaskLoggerPlugin !


Even I think this is the most useful plugin I have done, it is also the most unpopular. It may be due to the large amount of plugins already dealing with tasks, crons, jobs-queues and so on... sfDoctrineCronManagerPlugin, axCronPlugin, sfMCronPlugin, sfJobQueuePlugin, sfGearmanPlugin. I must admit I didn't tried the others as mine fits my needs and the ones of the companies I worked for until now.

sfProjectAnalyserPlugin

sfProjectAnalyserPlugin
  • User counts: 27 (+27 users since 7 jan 2011)
  • Available for: 1.4, 1.3, 1.2
  • Users feedbacks: 7
  • I like and use the sfProjectAnalyserPlugin !


This is my last plugin (well "our" plugin as I was not the only to contribute, thanks to all the contributors !) This is probably the most interesting as people where quiet curious about it and we had quiet a lot of positive feedbacks. What is it for ?

The sfProjectAnalyserPlugin allows you to analyse your symfony project, it can raise several coding standards alerts. A YAML configuration file allows you to switch what to analyse and also allows you to parameter threshold for each alert. This plugin can be helpful in mainly two situations:

  • You quickly want to check the volumetry and code quality of a symfony project your are going to maintain.
  • While developing a project from scratch, as a continuous integration tool, to ensure that as the project grows, you keep on following the symfony coding standards you defined at the very beginning of your project.


Others plugins

  • RIP: sfJoomla15BridgePlugin, I gave the leadership of this plugin to another developer (but there is no more activity).
  • RIP: sfWorkbenchPlugin: The XML structure of the generated WB schema was quiet hard to parse and I didn't find time to finish its proof of concept. Nevertheless, I would be glad if someone could take over this plugin. It could be very useful and used by many "lazy" developers (Well like me !) :p


That's 208 "regular" users for all these plugins, which is quiet a good score. I think my "symfony1 plugin developer career" is now over. I hope they have been useful for some of you. Obviously I will continue to maintain theme if big bugs were discovered. But don't except major new features. And now let's publish my first Symfony2 "bundle". ^^

- page 1 of 4