#36858: Optimize `db_default` creation
-------------------------------------+-------------------------------------
               Reporter:  Adam       |          Owner:  Adam Johnson
  Johnson                            |
                   Type:             |         Status:  assigned
  Cleanup/optimization               |
              Component:  Database   |        Version:  dev
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  1
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 Currently, `Field._get_default()` returns a `lambda` that instantiates a
 new `DatabaseDefault` each time it is called. This expression is identical
 each time, so this work is wasted. We can optimize it by creating a single
 expression that is returned each time.

 Thanks to Adam Sołtysik for the hint in https://forum.djangoproject.com/t
 /faster-bulk-create-using-dictionaries/43891

 Benchmarked with a quick modification to the test suite:

 {{{#!diff
 diff --git ./tests/bulk_create/tests.py ./tests/bulk_create/tests.py
 index 397fcb9186..ddfe315c0c 100644
 --- ./tests/bulk_create/tests.py
 +++ ./tests/bulk_create/tests.py
 @@ -877,6 +877,16 @@ def test_db_default_field_excluded(self):
              2 if connection.features.can_return_rows_from_bulk_insert
 else 1,
          )

 +
 +    def test_benchmark(self):
 +        import time
 +        start = time.perf_counter()
 +        DbDefaultModel.objects.bulk_create(
 +            [DbDefaultModel(name=f"obj {i}") for i in range(100_000)]
 +        )
 +        end = time.perf_counter()
 +        print(f"{end - start:.3f} seconds")
 +
      @skipUnlessDBFeature(
          "can_return_rows_from_bulk_insert",
 "supports_expression_defaults"
      )
 }}}

 Run with:

 {{{
 ./runtests.py --parallel 1
 bulk_create.tests.BulkCreateTests.test_benchmark -v 0
 System check identified no issues (0 silenced).
 0.617 seconds
 ----------------------------------------------------------------------
 Ran 1 test in 0.618s

 OK
 }}}

 Results, best of 3:

 Before: 0.691 seconds
 After: 0.610 seconds

 A ~12% speedup on this `bulk_create()` operation, on a model with a single
 `db_default` field.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36858>
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 [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/0107019baf6118cf-293d0496-f57f-47f7-8a39-c5c8a06b4f44-000000%40eu-central-1.amazonses.com.

Reply via email to