One problem I sort of always had with the ActiveRecord''s tight coupling to the SQL backend is how slow it makes the unit tests. OK, there are some ways to make it faster at a price of extra complexity (reusing the fixtures, doing a rollback in the end of the test, etc), but still - it is much slower than what I would like a unit test to be. Today I had a very simple idea (why, oh why didn''t I have it half a year ago?!). Set up a RAMDrive (a memory area treated by the OS as a virtual "disk") and put SQLite3 database on it. Voila! RForum test suite in 32 seconds instead of 104. -- Best regards, Alexey Verkhovsky Ruby Forum: http://ruby-forum.org (moderator) RForum: http://rforum.andreas-s.net (co-author) Instiki: http://instiki.org (maintainer)
On May 2, 2005, at 10:21 PM, Alexey Verkhovsky wrote:> One problem I sort of always had with the ActiveRecord''s tight > coupling to the SQL backend is how slow it makes the unit tests. > OK, there are some ways to make it faster at a price of extra > complexity (reusing the fixtures, doing a rollback in the end of > the test, etc), but still - it is much slower than what I would > like a unit test to be. > > Today I had a very simple idea (why, oh why didn''t I have it half a > year ago?!). Set up a RAMDrive (a memory area treated by the OS as > a virtual "disk") and put SQLite3 database on it. > Voila! RForum test suite in 32 seconds instead of 104.Give SQLite 2 a shot; it should be even faster. Better still, turn off instantiated fixtures (which require an extra database lookup per fixture, per test case) and turn on transactional fixtures (which use database transactions to isolate your test cases rather than deleting and reinserting fixtures for each test case.) class MyTest < Test::Unit::TestCase self.use_instantiated_fixtures = false self.use_transactional_fixtures = true def test_whatever # ... end end Or, to set as the default for all your tests, put this in test/ test_helper.rb: class Test::Unit::TestCase self.use_instantiated_fixtures = false self.use_transactional_fixtures = true end Enjoy, jeremy
On Tuesday 03 May 2005 01:46 am, Jeremy Kemper wrote:> On May 2, 2005, at 10:21 PM, Alexey Verkhovsky wrote: > > One problem I sort of always had with the ActiveRecord''s tight > > coupling to the SQL backend is how slow it makes the unit tests. > > OK, there are some ways to make it faster at a price of extra > > complexity (reusing the fixtures, doing a rollback in the end of > > the test, etc), but still - it is much slower than what I would > > like a unit test to be. > > > > Today I had a very simple idea (why, oh why didn''t I have it half a > > year ago?!). Set up a RAMDrive (a memory area treated by the OS as > > a virtual "disk") and put SQLite3 database on it. > > Voila! RForum test suite in 32 seconds instead of 104. > > Give SQLite 2 a shot; it should be even faster. >MySQL has an option for "MEMORY (HEAP)" databases that won''t even go through the file system code. Haven''t tested it, but I used to use a similiar concept in Java tests. David
On May 3, 2005, at 3:27 AM, David Corbin wrote:> On Tuesday 03 May 2005 01:46 am, Jeremy Kemper wrote: >> On May 2, 2005, at 10:21 PM, Alexey Verkhovsky wrote: >>> One problem I sort of always had with the ActiveRecord''s tight >>> coupling to the SQL backend is how slow it makes the unit tests. >>> OK, there are some ways to make it faster at a price of extra >>> complexity (reusing the fixtures, doing a rollback in the end of >>> the test, etc), but still - it is much slower than what I would >>> like a unit test to be. >>> >>> Today I had a very simple idea (why, oh why didn''t I have it half a >>> year ago?!). Set up a RAMDrive (a memory area treated by the OS as >>> a virtual "disk") and put SQLite3 database on it. >>> Voila! RForum test suite in 32 seconds instead of 104. >>> >> >> Give SQLite 2 a shot; it should be even faster. > > MySQL has an option for "MEMORY (HEAP)" databases that won''t even > go through > the file system code. Haven''t tested it, but I used to use a similiar > concept in Java tests.You can do the same for SQLite by specifying '':memory:'' as the file name. I think this is a fairly recent feature, so perhaps it isn''t available pre-3.0. jeremy
What impact does this have on unit tests?> You can do the same for SQLite by specifying '':memory:'' as the file > name. I think this is a fairly recent feature, so perhaps it isn''t > available pre-3.0.-- Tobi http://www.snowdevil.ca - Snowboards that don''t suck http://www.hieraki.org - Open source book authoring http://blog.leetsoft.com - Technical weblog
It should be much faster with the in-memory test databases. Not a bad idea at all! But, how do you keep the databases in sync? Do you have to develop on sqlite too? This brings up another issue. Is it worth it to have multiple testing setups to make sure your app runs flawlessly on multiple databases? On 5/3/05, Tobias Luetke <tobias.luetke-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> What impact does this have on unit tests? > > > You can do the same for SQLite by specifying '':memory:'' as the file > > name. I think this is a fairly recent feature, so perhaps it isn''t > > available pre-3.0. > > -- > Tobi > http://www.snowdevil.ca - Snowboards that don''t suck > http://www.hieraki.org - Open source book authoring > http://blog.leetsoft.com - Technical weblog > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- rick http://techno-weenie.net
On May 3, 2005, at 10:15 AM, Tobias Luetke wrote:> What impact does this have on unit tests? >> You can do the same for SQLite by specifying '':memory:'' as the file >> name. I think this is a fairly recent feature, so perhaps it isn''t >> available pre-3.0.I haven''t tried. When AR sees a relative path for dbfile in database.yml it prepends RAILS_ROOT, so specifying :memory: would try to load a database at the file path RAILS_ROOT/:memory:. That''d need a little workaround. jeremy
On May 3, 2005, at 10:18 AM, Rick Olson wrote:> But, how do you keep the databases in sync? Do you have to develop on > sqlite too?Yes. Keep the schema in sync. rforum goes so far as to use an erb template that''s rendered with the database specifics. It''s easy if you are mostly SQL-agnostic already.> This brings up another issue. Is it worth it to have multiple testing > setups to make sure your app runs flawlessly on multiple databases?If it''s worth running on multiple databases, it''s certainly worth testing on them! By maintaining compatibility you''ll probably end up with a cleaner app, too. jeremy
Alexey Verkhovsky
2005-May-04 06:09 UTC
Re: SQLite3 + RAM drive => 3 times faster unit tests
Jeremy Kemper wrote:> I haven''t tried. When AR sees a relative path for dbfile in > database.yml it prepends RAILS_ROOT, so specifying :memory: would try > to load a database at the file path RAILS_ROOT/:memory:. That''d need > a little workaround.The problem with :memory: option is that you need to create database tables on every run, so it''s a little bit more workaround. RAMDrive is good in that it keeps the state when the connecting processes are all down (until reboot, of course). Wiping and recreating the whole database is just a matter of rm b:\*; ruby script/create_db. Keeping in mind that RAMDrve eliminates all physical seeks, anyway, and that Ruby interpreter is probably slow while OS I/O routines are probably fast, I would be surprised to have any noticable difference between :memory: option and the RAMDrive, as far as RForum unit tests are concerned. Ditto for rollback vs commit, by the way - if there is no moving the head and waiting for the wanted disk sector to come under it, commit should be almost like a noop. I may be dead wrong in all that I say above, of course - misguided performance assumptions are something I make every day (what else would you do with a job title like "Performance Testing Expert"?) :) -- Best regards, Alexey Verkhovsky Ruby Forum: http://ruby-forum.org (moderator) RForum: http://rforum.andreas-s.net (co-author) Instiki: http://instiki.org (maintainer)