Opened 20 months ago
Last modified 20 months ago
#35270 closed Cleanup/optimization
Optimize Model._meta._property_names — at Initial Version
| Reported by: | Adam Johnson | Owned by: | Adam Johnson |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Keryn Knight | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Optimize Model._meta._property_names
Continuing my project to optimize the system checks, I found some optimizations for Options._meta._property_names, which I found to take ~4% of the total runtime for checks.
Most of this function’s runtime was being spent running inspect.getattr_static(). This is not surprising as it jumps through many hoops in order to avoid triggering attribute access.
I added use of getattr_static() back in #28269 / ed244199c72f5bbf33ab4547e06e69873d7271d0 to fix a bug with instance descriptors. But I think it’s overly cautious, and we can assume that accessing the __dict__ of the model class will work fine.
Two optimizations make the function run in negligible time:
- Changing the function to use
__dict__directly - Caching on a per-class basis. This requires using a weak-reference to classes, as we shouldn’t mutate base classes in the MRO, some of which can be non-model subclasses, like
Modelitself for thepkproperty,object, or any mixins.
Before optimization stats:
106 calls to _property_names took 26ms, or ~4% of the total runtime of system checks.
After optimization:
The same calls take 1ms, or ~0.2% of the total runtime. (The real runtime may be <1ms, but shows as 1 due to rounding up by cProfile.)