#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.

Reply via email to