Published by Fabian on 10 Oct 2007 at 08:03 pm
Performance Patch for Propel im symfony
Carsten came today to me and told me that he had an exciting finding:
$entity = $myObject->getEntity(); echo($entity); echo($entity);
is faster than:
echo($myObject->getEntity()); echo($myObject->getEntity());
I couldn’t believe that but it was the truth. When I dug deeper in propel i found this line generated [reformatted]:
public function getEntity($con = null) { include_once 'lib/model/om/BaseEntityPeer.php'; if ($this->aEntity === null && ($this->entity_gid !== null)) { $this->aEntity = EntityPeer::retrieveByPK($this->entity_gid, $con); } return $this->aEntity; }
so, what is the magic here? as you might know, include_once comes with a performance hit. and here you will get this performance hit each and every time you call the getter. Isn’t that annoying?
I found the guilty propel builder and did a small patch which places the include inside the if (where it is actually needed) and the performance hit is gone. Neat, isn’t it?
The patch can be found here: PHP5ComplexObjectBuilder.patch
Enjoy!
Stefan on 10 Oct 2007 at 10:00 pm #
But isn’t it always better to call a method once if you’re going to repeatedly access the value? Because method calling has a small performance hit anyway… or at least this is what I understood.
Still, this is a very good find. This getter is actually a bit strange: No local caching of already fetched data is a bit dirty imho.
Stefan on 10 Oct 2007 at 10:00 pm #
No, nevermind that last remark, there is actually caching. I should read the code better before responding
Fabian on 11 Oct 2007 at 7:48 am #
Yes there is caching
Of course you are right. Its a question of consuming memory for a reference or doing a method call (which result in very few stack operations). Generally for code readability and maintainability I prefer using the same getter 2-3 times. When I use it often I start thinking about “copying” the variable into the “codespace”. Which in typed languages has the advantage that you can see the datatype.
Of course it depends on the expectations. but i expect getters to be as fast as possible.
Eric on 11 Oct 2007 at 10:13 am #
Hello
I think you can remove this include_once call thank to symfony’s autoloading system
Just take a look at the config_autoload.yml.php file in the cache directory and you will see that every class defined in your model is registered in this file.
Fabian on 11 Oct 2007 at 11:09 am #
Hi Eric,
thanks for your comment. you are right. If used with standard autoloading in symfony the call is not required at all. But this is propel generated code. Which, I assume, should work also outside symfony. so from that the cleanest solution is to keep the include, just put it where it is absolutely needed.
But perhaps thats a good idea for an improvement the code compacter. It already removes comments to reduce the file size. It could also remove the include_once calls
Thierry on 11 Oct 2007 at 11:09 am #
Definitely they should have placed the include in the if statement. Good fix!
Which version of Propel has this problem?
Sinon on 11 Oct 2007 at 4:43 pm #
yeah, I always used the first, because it’s the same entity, and unless it is modified from call to call, its faster either way.. I think its just better coding..
Bert-Jan on 09 Jan 2008 at 10:59 am #
I’m using Propel 1.3 in my current project and with addIncludes set to false the includes in the base classes are actually gone. I haven’t tested to see where the include is put when addIncludes is turned on.
The include statement at the top of the subclasses (under model/) is still there though.
Bert-Jan on 10 Jan 2008 at 11:44 pm #
Correction: the includes in the subclasses are also gone. They were just some files from Propel 1.2 that 1.3 didn’t replace when I installed the plugin and ran propel-13-build-model.