testing for n+1 query regressions

101 views
Skip to first unread message

Paul Annesley

unread,
Sep 2, 2012, 10:34:05 PM9/2/12
to rails-...@googlegroups.com
I recently read a post about writing tests to catch n+1 query regressions, but I have no idea where it was.

I'm not sure it's a good idea (or possible to do in a non-fragile way), but it would be useful at this phase of an app I'm working on.

Does anybody remember the post, or have any thoughts on the matter?

— Paul

Tim McEwan

unread,
Sep 2, 2012, 11:56:18 PM9/2/12
to rails-...@googlegroups.com
Could you set bullet* to run in your test env and assert that you don't see its log output?  It would slow your tests down a fair bit though.

Don't worry, I'm aware this is a terrible idea - but hopefully it gets the ball rolling.

--
You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group.
To post to this group, send email to rails-...@googlegroups.com.
To unsubscribe from this group, send email to rails-oceani...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.

Mark Wotton

unread,
Sep 2, 2012, 11:59:50 PM9/2/12
to rails-...@googlegroups.com
I think it's a pretty bad idea to mix up benchmarking and correctness tests.

mark
--
A UNIX signature isn't a return address, it's the ASCII equivalent of a
black velvet clown painting. It's a rectangle of carets surrounding a
quote from a literary giant of weeniedom like Heinlein or Dr. Who.
-- Chris Maeda

Paul Annesley

unread,
Sep 3, 2012, 12:18:32 AM9/3/12
to rails-...@googlegroups.com
Each sub-resources I add to an API representation introduces an n+1.
I'd like a test to fail until I adjust the eager-loading accordingly.
Seems pragmatic, despite the dangers of testing for performance optimisations.

I've gone with this for the moment:
https://gist.github.com/3606669

The QuerySpy helps assert that increasing the number of records fetched does not increase the number of queries:

it "should not exhibit n+1" do
add_thing
count1 = QuerySpy.count { get "/things" }
add_thing
count2 = QuerySpy.count { get "/things" }
count2.should <= count1
end

The API could be fancier, but it does the job.
I can break eager-loading and see it fail, fix it and see it pass.

— Paul

Craig Read

unread,
Sep 2, 2012, 10:48:13 PM9/2/12
to rails-...@googlegroups.com
I don't remember seeing a post on this, but do remember watching the Railscast on Bullet recently.


— Paul

--
You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group.
To post to this group, send email to rails-...@googlegroups.com.
To unsubscribe from this group, send email to rails-oceani...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.

Malcolm Locke

unread,
Sep 2, 2012, 10:58:24 PM9/2/12
to rails-...@googlegroups.com
There's a gem for that:

https://github.com/flyerhzm/bullet

Never used it though so cannot testify to it's effectiveness.

Malc

Paul Annesley

unread,
Sep 3, 2012, 6:56:26 AM9/3/12
to rails-...@googlegroups.com
Bullet does look cool, but as far as I know it doesn't provide assertions like I'm after.

The post I read was specifically about writing RSpec (or Test::Unit?) assertions based on number of queries.

The QuerySpy I ended up with works well for me.

— Paul

Fred Wu

unread,
Sep 4, 2012, 7:15:51 AM9/4/12
to rails-...@googlegroups.com
I've used Bullet briefly many moons ago but haven't used it for assertion. However, looking at Bullet's source, I think you might be able to wrap its `NPlusOneQuery` class for assertion? https://github.com/flyerhzm/bullet/blob/master/spec/bullet/detector/n_plus_one_query_spec.rb
Reply all
Reply to author
Forward
0 new messages