Optimize Model initialization by sending pre and post init signals only if there are listeners
|Reported by:||Anssi Kääriäinen||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||1.3|
|Cc:||anssi.kaariainen@…||Triage Stage:||Design decision needed|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||yes|
The attached patch implements an optimization to Model object initialization. The idea is to check if there are any listeners to signals. If not, then we can skip the sending and save time. The attached benchmark.tar.gz has some tests. Unpack and run python speedtester.py. See the file for details.
The most interesting test is a loop of 10000 model initializations with a post and pre init signal listeners connected to a _different_ model. The result is that pre patch it takes 0.21 seconds to initialize objects, after patch only 0.07 seconds.
This situation is interesting because
GenericForeignKey will attach to pre_init signal, and
ImageField to post_init signal. So if you have both you will pay 0.14 seconds extra for every batch of 10000 objects created. That is true for all models in your project. After patch, you will pay the price only when there is somebody actually listening.
The patch is complete, expect that I don't know if support for .connect() without sender kwarg is needed. It is possible to support that case also, though a little more code is needed.
As a completely non-scientific data point, the test suite ran 2% faster after patch (and was passed).