Opened 8 years ago

Closed 8 years ago

#25750 closed Cleanup/optimization (fixed)

During makemigrations Options._expire_cache takes 30% of the time

Reported by: Patryk Zawadzki Owned by: Patryk Zawadzki
Component: Migrations Version: 1.8
Severity: Normal Keywords:
Cc: 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

Here's the profiler output:

         215373161 function calls (214826612 primitive calls) in 282.839 seconds

   Ordered by: internal time
   List reduced from 6484 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  5225318   59.334    0.000   89.667    0.000 django/db/models/options.py:711(_expire_cache)
 40538898   27.751    0.000   27.751    0.000 {delattr}
 16538241   18.624    0.000   38.450    0.000 django/apps/config.py:164(get_models)
   485536   16.907    0.000   27.126    0.000 django/db/models/fields/__init__.py:358(deconstruct)
  4466221   12.337    0.000   20.062    0.000 /usr/lib64/python2.7/collections.py:109(values)
    79811   10.893    0.000   53.060    0.001 django/apps/registry.py:153(get_models)
    73250   10.582    0.000   43.745    0.001 django/db/models/fields/related.py:317(swappable_setting)
   495362    8.314    0.000   11.430    0.000 django/db/models/fields/__init__.py:137(__init__)
 24359432    7.790    0.000    7.790    0.000 /usr/lib64/python2.7/collections.py:78(__iter__)
15623269/15397100    7.142    0.000    7.330    0.000 {getattr}

I have a pull request ready that makes it slightly better:

         164872486 function calls (164325937 primitive calls) in 199.897 seconds

   Ordered by: internal time
   List reduced from 6484 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 16538241   18.580    0.000   38.545    0.000 django/apps/config.py:164(get_models)
   485536   16.290    0.000   26.736    0.000 django/db/models/fields/__init__.py:358(deconstruct)
  4466221   12.357    0.000   20.069    0.000 /usr/lib64/python2.7/collections.py:109(values)
    79811   10.933    0.000   53.182    0.001 django/apps/registry.py:153(get_models)
    73250   10.694    0.000   43.931    0.001 django/db/models/fields/related.py:317(swappable_setting)
  5225318    9.295    0.000    9.406    0.000 django/db/models/options.py:711(_expire_cache)
   495362    8.807    0.000   11.958    0.000 django/db/models/fields/__init__.py:137(__init__)
 24359432    7.777    0.000    7.777    0.000 /usr/lib64/python2.7/collections.py:78(__iter__)
15623269/15397100    7.316    0.000    7.504    0.000 {getattr}
        2    4.863    2.431    4.863    2.431 {raw_input}

Change History (7)

comment:1 by Patryk Zawadzki, 8 years ago

Has patch: set

comment:2 by Tim Graham, 8 years ago

Triage Stage: UnreviewedReady for checkin

comment:3 by Marten Kenbeek, 8 years ago

Triage Stage: Ready for checkinAccepted

Can you get a similar result using actual timing functions such as timeit? I've looked into this before, and if my memory serves me right the results of profiling in this case are highly skewed, and the actual improvements are barely noticeable.

Another thing to keep in mind is that #24397 greatly reduces the number of calls to _expire_cache().

comment:4 by Patryk Zawadzki, 8 years ago

In my case it is noticeably faster even if the act of profiling itself skews the results by making function call more expensive. The slowest part was depending on try/except to trap nonexistent attributes. It may not make much difference in most projects but the one I work for takes several minutes to generate migrations.

comment:5 by Marten Kenbeek, 8 years ago

Triage Stage: AcceptedReady for checkin

It would be interesting to know why it makes such a difference in some projects, and none in others.

comment:6 by Patryk Zawadzki, 8 years ago

I suppose with #24397 it will make a much smaller difference. In our case according to migrate --list there are 35 apps with 221 migrations.

comment:7 by Tim Graham <timograham@…>, 8 years ago

Resolution: fixed
Status: newclosed

In 7628f87e:

Fixed #25750 -- Made Options._expire_cache() faster

Avoided unnecessary list operations and delattr() calls that result
in an exception being raised as it causes call frame reconstruction
which is very costly, especially so in a function that is called
millions of times.

Note: See TracTickets for help on using tickets.
Back to Top