Improving Test Speed for Projects that use django.contrib.postgres

266 views
Skip to first unread message

David Muller

unread,
May 4, 2015, 1:01:51 PM5/4/15
to django-d...@googlegroups.com
Hi everybody,

Recently I've begun to use the PostgreSQL specific fields introduced in Django 1.8.  My codebase actually uses the special fields (HStoreField and ArrayField mostly) frequently enough such that I cannot run my test suite on an in memory SQLite database -- I have to run on a PostgreSQL instance.

Running my tests on PostgreSQL is fine, but I miss the zippy performance of an in memory SQLite database.  If, say, my test code cannot be refactored itself, what would be your suggested route for test speed improvement?  I see this outstanding django ticket for UNLOGGED postgres tables, and also some work by aaugustin towards adding a `--parallel` option to the django tests.  Another thought I had would be creating "dumb" versions of the PostgreSQL fields that worked in SQLite. 

I realize, of course, that by using `django.contrib.postgres`, I should expect to sacrifice Django's "plug and play database backends" -- still curious as to your thoughts of improving test speed for projects that use postgres specific fields.

Thanks!

Marc Tamlyn

unread,
May 4, 2015, 2:45:55 PM5/4/15
to django-d...@googlegroups.com
One of the main questions is to work out what is slow. You can often gain a lot by using the new --keep-db option which maintains the test database between runs meaning you don't have the DDL time each run.

A brute force approach which can have an impact is to install postgres on a RAM disk, this does have some significant performance implications.

If you are running linux or a brew-installed postgres, it's also possible that your postgres instance is configured poorly for local development. Christophe Pettus gave a talk a while back (slides[1]) which gives an overview of some of the common flags you may want to change from their 1990s defaults. In particular the section on memory may be appropriate.

The ideal way to avoid this though is simply to not use the database as much as possible. There are various ways to approach this, from mocking it out, to unit testing various objects, to building ORM objects without ever calling .save() on them. There are a number of resources online for this.

Personally, I tend not to worry too much about my overall test suite's speed, so long as I can run the tests for the section I'm working on well I then rely on the CI to deliver my final answers. As a side note, your CI should always be trying to mimic live as much as possible - even if you were to use SQLite locally for testing Django cannot guarantee all behaviour is completely db agnostic, especially when it comes to constraint checking.

Marc


--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/32aa98c9-a05f-456f-bd0e-96d324104448%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

David Muller

unread,
May 5, 2015, 12:15:15 AM5/5/15
to django-d...@googlegroups.com
Thanks for the helpful advice, Marc.  

I toyed with my settings a bit (especially the memory ones -- upping shared_buffers, work_mem and effective_cache_size) to be in line with the suggestions in Christophe Pettus' talk, but did not observe a significant change in the speed of test my suite.  Assuming I haven't really screwed up the configuration, my guess would be that changing the settings had minimal effect on test speed is because my test suite never shovels a significant amount of data towards postgres.  

Haven't had a chance to try and throw everything into RAM disk but that sounds pretty cool.

Your final suggestion about only running a subset of tests rings true with me:

Personally, I tend not to worry too much about my overall test suite's speed, so long as I can run the tests for the section I'm working on well I then rely on the CI to deliver my final answers

I feel the same way and constantly target particular subsets of my tests, but it's always tempting to see if everything can run a little quicker!  Thanks again for the response and advice.

- David

Aymeric Augustin

unread,
May 5, 2015, 2:46:28 AM5/5/15
to django-d...@googlegroups.com
2015-05-05 6:15 GMT+02:00 David Muller <daveh...@gmail.com>:
Haven't had a chance to try and throw everything into RAM disk but that sounds pretty cool.

Actually, that's the reason why I added support for tablespaces on PostgreSQL in Django 1.4 :-)

https://docs.djangoproject.com/en/1.8/ref/settings/#default-index-tablespace

I remember that it was easy to set up and worked well. It made a good difference on the CI server, which had traditional hard disks, but not an appreciable change locally on my laptop, which has a SSD.

--
Aymeric.

Curtis Maloney

unread,
May 5, 2015, 2:54:47 AM5/5/15
to django-d...@googlegroups.com
I looked into using UNLOGGED some time ago, but the create table method was misnamed, and the actual create table function was inflexible.

Now the code is much cleaner, and each DB can specify how to enact create table and friends.

Which leaves us with the question -- is it possible to alter the Schema strings based on if we're running tests?

The closest I can see is sql_table_creation_suffix...

If there were a similar function which allowed us to pass additional arguments for substing into sql_create_table...

--
C


--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
Reply all
Reply to author
Forward
0 new messages