Hi to both lists. I've done a simple benchmark to compare Sequel and DataMapper performance. It's a not very completed test.
I just would like to receive your opinions about the results. ###################################### ## Benchmark: Sequel VS DataMapper ## ###################################### This is a simple Rack application using Thin web server in localhost. The benchmark is based on Apache 'ab' command (a testing HTTP client): ab -n 10000 -c 10 http://127.0.0.1:9292 This means: - 10000 requests - Concurrency: 10 When a HTTP request arrives to the server, Rack gets the 'doc' column from a MySQL table searching for 'username', 'domain' and 'doc_type' fields. In the table there is an UNIQUE key composed by these four columns: username domain doc_type doc_uri This means that, due my queries type, I'm not using indexes. However, the table has just 26 rows. In all the tested cases, the only column queried is 'doc'. The retrieved document (a XML document) is sent in the reply body. --------------------------------------------------------------------------------- a) Using Sequel For each HTTP request the following code is performed: doc = DB::DbStorage[:storage]. \ filter(:username => "alice", :domain => "example.org", :doc_type => 2). \ limit(1).select(:doc).first status = ( doc ? 200 : 404 ) body = ( doc ? doc[:doc] : "" ) It generates the following SQL query: Query SELECT `doc` FROM `storage` WHERE ((`doc_type` = 2) AND (`domain` = 'example.org') AND (`username` = 'alice')) LIMIT 1 Result: top output during the test: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 15072 root 20 0 91664 24m 4232 R 85 1.2 0:20.23 ruby1.8 16166 mysql 20 0 296m 45m 6080 S 11 2.3 1:27.06 mysqld ab output: Document Length: 831 bytes Concurrency Level: 10 Time taken for tests: 18.143 seconds Complete requests: 10000 --------------------------------------------------------------------------------- b) Using Sequel with MySQL prepared stament: When the server start the prepared stament is created: ds_get_document = DbStorage[:storage]. \ filter(:username => :$n1, :domain => :$n2, :doc_type => :$n3). \ limit(1).select(:doc) PsGetDocument = ds_get_document.prepare(:select, :get_document) For each HTTP request the following code is performed: doc = PsGetDocument.call(:n1 => "alice", :n2 => "example.org", :n3 => 2).first status = ( doc ? 200 : 404 ) body = ( doc ? doc[:doc] : "" ) It generates the following SQL queries: Query SET @sequel_arg_1 = 2 Query SET @sequel_arg_2 = 'sipdoc.net' Query SET @sequel_arg_3 = 'ibc' Query EXECUTE get_document USING @sequel_arg_1, @sequel_arg_2, @sequel_arg_3 Execute [1] SELECT `doc` FROM `storage` WHERE ((`doc_type` = 2) AND (`domain` = 'sipdoc.net') AND (`username` = 'ibc')) LIMIT 1 (note that the last query is autogenerated by MySQL instead of sent by Sequel) Result: top output during the test: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 15324 root 20 0 92600 25m 4236 R 65 1.3 0:06.17 ruby1.8 16166 mysql 20 0 296m 45m 6080 S 30 2.3 1:31.30 mysqld ab output: Document Length: 831 bytes Concurrency Level: 10 Time taken for tests: 18.913 seconds Complete requests: 10000 --------------------------------------------------------------------------------- c) Using DataMapper: For each HTTP request the following code is performed: doc = DB::Document.first(:username => "alice", :domain => "example.org", :doc_type => 2) status = ( doc ? 200 : 404 ) body = ( doc ? doc.doc : "" ) It generates the following SQL query: Query SELECT `doc` FROM `storage` WHERE (`username` = 'alice') AND (`doc_type` = 2) AND (`domain` = 'example.org') LIMIT 1 Result: top output during the test: PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 15516 root 20 0 112m 37m 4248 R 92 1.9 0:35.43 ruby1.8 16166 mysql 20 0 296m 45m 6080 S 5 2.3 1:36.26 mysqld ab output: Document Length: 831 bytes Concurrency Level: 10 Time taken for tests: 16.452 seconds Complete requests: 10000 --------------------------------------------------------------------------------- Summary: Sequel Sequel(prep. stament) DataMapper ruby1.8 cpu usage: 85% 65% 92% mysqld cpu usage: 11% 30% 5% ruby1.8 mem usage: 1.2% 1.3% 1.9% mysqld mem usage: 2.3% 2.3% 2.3% test time (seconds): 18.143 18.913 16.452 My opinions: - It seems that, without prepared staments, DataMapper is a bit faster than Sequel when performing the same query. - Without prepared staments, DataMapper consumes more CPU than Sequel but makes MySQL to consume less (I cannot understand why since the query is exactly the same). - When using Sequel prepared staments, there are three SQL queries for each request so MySQL works more and has higher CPU usage. However, Ruby process seem to consume much less CPU. Sincerelly, I cannot get a conclussion from this benchmark, but DataMapper seems a bit faster. Anyhow DataMapper doesn't support prepared staments. -- Iñaki Baz Castillo <[email protected]> --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "DataMapper" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/datamapper?hl=en -~----------~----~----~----~------~----~------~--~---
