#27624: Optimize ORM by using more immutable data structures -------------------------------------+------------------------------------- Reporter: Adam Chainz | Owner: Adam Type: | Chainz Cleanup/optimization | Status: assigned Component: Database layer | Version: 1.10 (models, ORM) | Severity: Normal | Resolution: Keywords: | Triage Stage: Accepted Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------------+-------------------------------------
Comment (by Adam Chainz): Note: if all of `Query`'s attributes were immutable, we could probably greatly speed up its instantiation and copying by not having every attribute defined on every instance, and relying on fallback to class level defaults, then `clone()` doing a simple `new.__dict__.update(self.__dict__)` to copy all the non-default attributes. For example, take these two classes: {{{ In [24]: class Foo(object): ...: def __init__(self): ...: self.x = None ...: self.y = None ...: self.z = None ...: def clone(self): ...: obj = self.__class__() ...: obj.x = self.x ...: obj.y = self.y ...: obj.z = self.z ...: return obj ...: In [25]: class Foo2(object): ...: x = None ...: y = None ...: z = None ...: def __init__(self): ...: pass ...: def clone(self): ...: obj = self.__class__() ...: obj.__dict__.update(self.__dict__) ...: return obj ...: }}} The first example corresponds to the current situation with `Query`, and the bottom is the imagined future. Timing the example `__init__` + `clone()` methods gives: {{{ In [26]: %timeit -n 1000000 -r 3 Foo().clone() 1000000 loops, best of 3: 1.82 µs per loop In [27]: %timeit -n 1000000 -r 3 Foo2().clone() 1000000 loops, best of 3: 1.3 µs per loop }}} This is about a 30% speed up. Inspecting just the `clone()` methods because we care a bit more about the time that takes over `__init__`, gives us: {{{ In [31]: foo = Foo() In [32]: %timeit -n 1000000 -r 3 foo.clone() 1000000 loops, best of 3: 1.15 µs per loop In [33]: foo2 = Foo2() In [34]: %timeit -n 1000000 -r 3 foo2.clone() 1000000 loops, best of 3: 874 ns per loop }}} About a 25% speed boost, very similar. The difference will hopefully be even greater on `Query` as currently its `clone()` method is 69 lines long with many attributes getting copied. -- Ticket URL: <https://code.djangoproject.com/ticket/27624#comment:5> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/068.788a1b7f58c934bb9a74373af307d402%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.