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
-~----------~----~----~----~------~----~------~--~---

Reply via email to