﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
19501	Allow for fast path model loading	Anssi Kääriäinen	Anssi Kääriäinen	"I have been playing around with the idea of pushing the model construction to a class method of the model. This will allow very fast reads from database, around 2x faster for normal model, 4x faster for deferred model when you override the from_db() so that it constructs the model directly using the model.__dict__ and doesn't send any signals. With signal sending the speed different is 1.2x for normal model, ~3x for deferred model.

Of course, you can't do that by default. This breaks multiple things: setattr not called (and descriptors don't work either), overridden init not called and of course no signals sent. So, the default would need to be old good `__init__` way, or we would need to make a really big backwards compatibility break.

Still, in most projects where model init is a performance bottleneck it will be for just one or two models. 90%+ of models do not need the signals, init call nor do they have any setter of interest in the from DB case. For these models it would be trivial to create a ""fast path readonly proxy"" for the performance bottleneck cases.

So, by adding the from_db method we could allow for really fast init for those who need it. The cost is around 5% slower for the default `__init__` case.

Actually, if you are not going to write the data back to the DB you can throw away the model._state, too. Then you get this kind of results:
{{{
Running 'model_init_signals' benchmark ...
Min: 0.007368 -> 0.002830: 2.6035x faster
Avg: 0.007430 -> 0.002847: 2.6100x faster
Significant (t=347.070697)
Stddev: 0.00006 -> 0.00001: 5.6553x smaller (N = 18)

Running 'query_all' benchmark ...
Min: 0.006640 -> 0.002699: 2.4600x faster
Avg: 0.006684 -> 0.002713: 2.4636x faster
Significant (t=687.137094)
Stddev: 0.00002 -> 0.00001: 2.3581x smaller (N = 18)

Running 'query_defer' benchmark ...
Min: 0.016939 -> 0.003011: 5.6257x faster
Avg: 0.017019 -> 0.003028: 5.6211x faster
Significant (t=1300.019953)
Stddev: 0.00004 -> 0.00001: 3.9626x smaller (N = 18)
}}}

I think the 5% slowdown for the default `__init__` path is worth it so that those who really need speed can achieve the above shown performance.

A really barebones patch at: https://github.com/akaariai/django/compare/fast_init - this can be used to run benchmarks but can't be included in Django as is - it doesn't have the safe `__init__` as the default."	Cleanup/optimization	closed	Database layer (models, ORM)	dev	Normal	fixed			Ready for checkin	1	0	0	0	0	0
