Tuesday, March 3, 2009

Symfony Speed and Hello World Benchmarks

After reading some posts showing that my blah blah framework is way more fast than symfony for a Hello World application I decided to explain why: because symfony is extensible and can adapt to your needs. That’s easy to say you may think, in fact, every framework out there claims that. So what makes symfony so special?


The following list names some of the features provided by symfony.

  • Factories
  • The Filter Chain 
  • The Configuration Cascade
  • The Plugins System
  • Controller adaptability
  • View adaptability


Factories


Since version 1.0 symfony provides a configuration file called factories.yml. This file affects the application core classes configuration. There you can override symfony default classes by your own ones. This means you can set up a custom Front Controller, Web Request, Cache classes, Session storage, etc. 


But this come with an extra price: when a symfony application bootstraps, it reads the configuration file from the filesystem. If the yml file was parsed before, then it loads a PHP file -which can also be cached with APC-, if not, then it parses the yml file, stores the parsed file on the cache folder and loads the configuration from there.


Why should I need that flexibility you may ask? In a project I’m involved with we needed Memcached. This means that we overrode all of the symfony default cache mechanism by our own custom classes. How? Setting up our classes in an easy to read yml file. So for sure when you benchmark your Hello World application symfony will be slower.


Filter Chain


One of the patterns from the Core J2EE Patterns book that impressed me the most is the Intercepting Filter. This patterns teach how to modify a request processing without the need to change Controllers or Model code. The idea is that in a configuration file you plug a class that will take care of pre or post processing the request. This classes are called filters. As an example, you can add a filter that checks if the user has the proper credentials to execute the action she wants. Another filter can cache the response, etc. 


Symfony has the filters.yml file which can be specified by application or by module. This means that we can set filters to be executed for the whole application, and then for specific modules -let’s say for Ajax actions-, we disable them. Does your framework provides this flexibility without resorting to some kind of monkey patching techniques? No? Well symfony does. Say hello to the Filter Chain. So for sure when you benchmark your Hello World application symfony will be slower. Because it adds flexibility to the process. You want to get rid of this behavior? Sure, set up a custom controller in the factories.yml file, and in your new class override the loadFilters method.


Configuration Cascade


As explained in the configuration chapter of the symfony book, symfony allows to modify it’s behavior through some yml files. So for example we have the view.yml that tells symfony which css and javascript files it should load for the current request. We can have an application view.yml configuration and then override the settings per module. When symfony process the request it checks all this files, that’s why in the Hello World benchmark it‘s slow.


Plugins System


Symfony has a very powerful and easy to use Plugin System. It’s more than 400 plugins with a set of 200+ developers speaks by itself of it success. 


The plugins can contain modules of their own and also a config.php file, similar to the project config.php file or the module config.php. When symfony process a request it checks for the settings in those files, this means that they will be read from disk. So in a plugin we can provide a custom logger that is fired up when bootstrapping the application. The Plugin user doesn’t need to care how the logger will be activated, she just now that it will work. 


The same applies for plugin modules. How do you think that symfony knows that certain module/action should be called from a plugin? If you enable the plugin module on the settings.yml file symfony will check inside the plugin module to see if the requested action should be executed there. 


Controller adaptability


For each action that the user call symfony will execute a page controller. Inside our modules symfony let us use a generic myModuleActions class that will extend sfActions or one specific to the action requested by the user, that as an example could be called indexAction and will extend the sfAction class. When a request is processed symfony first checks for the existence of the later. If it doesn’t exists then it tries to load the generic action for that module. Of course you don’t need this kind of flexibility for Hello World apps.


View Adaptability


For rendering the response symfony uses by default the sfPHPView class. If certain module in your application requires a different view, then there are at least three ways to accomplish this as explained here.


Conclusion


Symfony is a Professional Web Application Framework built to cope with real world needs. In a large project with more than a simple salutation feature sooner or later you will need the flexibility provided by the framework. This will save you time and will prevent headaches, because when you have built a whole system with a framework and the business needs start to push in a direction where you have to extend the framework you will thank yourself for having choose symfony at first.

In case that your client requires a Hello World! application, then you can use the following hyper fast framework code: die(“Hello World!”) ;-)

10 comments:

pmjones said...

All of the frameworks I benchmark in "hello world" situations (aka "baseline responsiveness" comparisons) implement *all* of the things you mention. Cake, Symfony, Solar, and Zend all implement some form of factories, filter chains, configurations, controller adaptability, and view adaptability.

http://paul-m-jones.com/?p=315

You will need to do better than that to show why Symfony is special and different.

Alvaro Videla said...

Hi,

Can you explain how all those frameworks implement those features? i. e.: Show what's the magic recipe that they follow to load the same amount of data from disc and then be faster? AFAIK as I know about ZF, it doesn't perform all of the checks that symfony does on the controller dispatch method. I may be wrong tough.

Do you know how symfony works inside in it's core as you call it in your article?

Jacky Hung said...

nice article.
compared with struts(the mvc framework in Java), i like symfony more. Because it's easier to user and faster to implement. Maybe we would give thanks to the agile nature of PHP.

But both of them have some same features more or less:

the Factories: In struts 1, it depended on the well-form nature of java. you can extend or implement class from the framwork core classes. With struts 2, it uses the famous "Sping" lib. The concept of Ioc (inverse on control) give developers a better chance to extend and replace the logic of the original framework without changing any code. actually ioc is everywhere in struts 2 from populating request parameters to actions to getting a DAO object. If symforny could involve Ioc, i think it will be more attractive.

Filter Chain: 5 years ago,(struts 1 for instance), we just used filter in Java. here filter is a real filter which basically pre-excute some logic before the main one. But in struts 2, it changes the name to interceptors which do the same as "Filter chain" in symfony. But what can be improved is : symfony should have a interface-like class (maybe abstract class) who contains 2 method : preExecute() and postExecute(), then any subclass 's logic is much clear. Since i've seen some bug caused by putting post-execute-logic wrongly before process() by mistake.

Configuration Cascade: very nice feature. struts should learn more from this(to improve at least). But now grails (something like symfony,rails in Groovy running in JVM) has this. btw rails 1.2 's performance is much better than before.

plugin: as developer, u can make your own plugin easily for both frameworks. and the plugin repository has a lot off-the-shelf plugins. But since symfony auto-load mechanism is not robust as java's, it will loose for performance sake.

Controller adaptability: as said before, with Ioc you can easily extend it to meet your need.

View: same as Controller. in java, you can also choose which tech you would like to render the page. like freemarker, Velocity, or the traditional JSP page. very flexible, right?


why i like symfony more:
1. it has command-line utilities which speed up development and save you from the boring configurations and machine steps.
(grails has the same functionality, so i like grails as well :))

2. symfony cooperate very well with html tags and Ajax. i have bad impress of ajax support in struts and not good experience with tags. Symfony does it really good. Especially for ajax support, the built-in is for prototype, and you can easily switch to jquery using plugin.

there is a lot to say, like the model level, performance tuning, memcache......

hope we can talk more shortly.

Alvaro Videla said...

Well Jacky what can I say... Your comment deserves a blog post on it's own!

Thanks for bringing your JAVA experience to the symfony community so we all can learn from each others :-)

mweierophinney said...

@Alvaro -- what @pmjones is suggesting is that each of the frameworks he benchmarks implement similar functionality. He's not suggesting that the functionality is implemented in the same way or loads the same number of files from disk -- in fact, far from it. Each implements these features in very different ways, and some will do so with more or fewer files. ZF, for instance, allows for cascading configuration -- but you don't need configuration for an application to work (unlike symfony).

The primary thing, however, is that @pmjones' benchmarks show the baseline performance -- i.e., what is the fastest an application written in a framework can run without adding any caching or external dependencies (such as database, web services, etc.). As such, his methodology is sound, and the benchmarks have value.

Should benchmarks against comparable applications also be made? Probably. But it would take a concerted effort by developers versed in each of the frameworks to do so, and I'm guessing that won't happen anytime in the near future.

Alvaro Videla said...

@mweierophinney I understand his point and yours also. But I don't see the goal of this kind of benchmarks. As @skoop said on twitter, I feel that this is like comparing pears and apples.

Now, can you please tell me if you don't need configuration to work, how does all the other frameworks nows how to connect to you project specific database? Or how to know what Front Controller to use, etc.? If that is not configuration, what is then?

And I don't want to start a flame war between frameworks, because that is stupid. I think that all of them have something to cool to give to the community, that's why people use them.

mweierophinney said...

@Alvaro -- ZF uses both convention and configuration -- but has sane defaults, which means that no configuration is necessary. Add a DB to the mix, and you need configuration. But ZF's approach to configuration is to do as much of it at the PHP level as possible -- no configuration files by default. You can use configuration files, but you don't need to. Configuration !== configuration file; configuration can also simply mean setting object state.

However, the point is, at the most basic level -- outputting a static page -- what is the fastest that a framework can provide? That's where @pmjones' benchmarks compare apples to apples, and it's the sole point of those benchmarks. It's not about which framework is fastest, it's about having some baseline for comparison down the road.

If you add a DB or web services into the mix, that number will decrease (as in, fewer requests per second). Add caching, however, and that number may increase. But the point is: what do I start with? And then you bench again later, after most of the application logic is in place. And then you bench again more when you have a variety of caching strategies in place.

I would never, ever base a decision on which framework to use on these statistics. I might, however, develop my application differently from the outset knowing this information. (E.g, do aggressive, granulated caching from the outset.)

Alvaro Videla said...

@mweierophinney

"ZF uses both convention and configuration -- but has sane defaults, which means that no configuration is necessary"

Symfony does that too. Init a project and application from the command line and you get your app up and running, zero configuration on your said.

"I would never, ever base a decision on which framework to use on these statistics"

Me too :-)

"I might, however, develop my application differently from the outset knowing this information."

I won't do any kind of premature optimization based in a hello world application benchmark. I will base my optimization based on how my application behaves in real life.

And in my post I'm showing how symfony works, so the developer can get an idea of what to expect from the framework. I even don't understand why you or @pmjones are defending the benchmarks on this article: http://paul-m-jones.com/?p=315

jminkler said...

All sheer lunacy, in ALL the frameworks die('Hello World'); is the fastest! If you "remove all that you don't need for benchmarks" then why not just run this code? So silly... What about ADDING plugins to each of the framework like in symfony sfSuperCache ?? Benchmark that?

A bunch of what if nonsense ..

Neil said...

Perhaps they are defending those benchmarks, because your post starts "After reading some posts showing that my blah blah framework is way more fast than symfony for a Hello World application I decided to explain why: because symfony is extensible and can adapt to your needs." which seems to be you saying Symfony is slow because it has these features, the problem being other frameworks also have those features, so your reasoning doesn't really hold up, you asked for an example of how other frameworks implement these things so I'll give you one (I'm not going to go through the lot, life is too short), but anyway.

Factories - overriding default classes, in codeigniter for example the default classes are stored in the libraries folder, on the same level is the app/ folder which contains rather unsurprisingly contains all the files you add, in that app folder is another folder called libraries, Codeigniter checks their first before the overall libraries folder a level up, so to override a base class simply place your class there.