<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -7,51 +7,114 @@ You can easily run your own benchmarks, as long as you have memcached itself on
 
 == x86-64 OS X
 
-These benchmarks were run on an OS X 10.5 Core 2 Duo machine (10,000 iterations):
+These benchmarks were run on an OS X 10.5 Core 2 Duo machine:
 
   Ruby 1.8.7p174
-  Loaded memcached 0.16.3
-  Loaded memcache-client 1.7.4
-
-                                           user     system      total        real
-  set:plain:noblock:memcached:net      0.260000   0.110000   0.370000 (  0.941733)
-  set:plain:noblock:memcached:uds      0.250000   0.060000   0.310000 (  0.470593)
-  set:plain:memcached:net              0.640000   1.040000   1.680000 (  4.352426)
-  set:plain:memcached:uds              0.500000   0.560000   1.060000 (  2.130330)
-  set:plain:memcache-client            7.500000   3.160000  10.660000 ( 11.394051)
-  set:ruby:noblock:memcached:net       0.430000   0.070000   0.500000 (  1.393856)
-  set:ruby:noblock:memcached:uds       0.440000   0.040000   0.480000 (  0.751106)
-  set:ruby:memcached:net               0.890000   0.910000   1.800000 (  5.539385)
-  set:ruby:memcached:uds               0.790000   0.610000   1.400000 (  3.257946)
-  set:ruby:memcache-client             7.710000   3.160000  10.870000 ( 11.494342)
-  get:plain:memcached:net              0.730000   0.940000   1.670000 (  4.305591)
-  get:plain:memcached:uds              0.610000   0.580000   1.190000 (  2.225602)
-  get:plain:memcache-client            8.960000   3.110000  12.070000 ( 13.710735)
-  get:ruby:memcached:net               0.910000   0.980000   1.890000 (  4.364018)
-  get:ruby:memcached:uds               0.750000   0.570000   1.320000 (  2.236862)
-  get:ruby:memcache-client             9.310000   3.180000  12.490000 ( 13.077060)
-  multiget:ruby:memcached:net          0.510000   0.350000   0.860000 (  1.471429)
-  multiget:ruby:memcached:uds          0.500000   0.260000   0.760000 (  1.138027)
-  multiget:ruby:memcache-client        4.840000   1.110000   5.950000 (  6.511808)
-  get-miss:ruby:memcached:net          0.960000   1.030000   1.990000 (  4.510132)
-  get-miss:ruby:memcached:uds          0.830000   0.640000   1.470000 (  2.708862)
-  get-miss:ruby:memcache-client        7.810000   3.190000  11.000000 ( 11.390215)
-  append-miss:ruby:memcached:net       1.000000   1.030000   2.030000 (  4.923893)
-  append-miss:ruby:memcached:uds       0.890000   0.680000   1.570000 (  3.202743)
-  append-miss:ruby:memcache-client     7.740000   3.180000  10.920000 ( 11.339136)
-  mixed:ruby:noblock:memcached:net     1.800000   2.370000   4.170000 (  8.616549)
-  mixed:ruby:noblock:memcached:uds     1.410000   1.090000   2.500000 (  5.035893)
-  mixed:ruby:memcached:net             1.830000   1.900000   3.730000 (  9.046367)
-  mixed:ruby:memcached:uds             1.570000   1.190000   2.760000 (  6.583020)
-  mixed:ruby:memcache-client          17.910000   6.440000  24.350000 ( 24.946386)
-  hash:murmur                          0.040000   0.000000   0.040000 (  0.039152)
-  hash:default                         0.040000   0.000000   0.040000 (  0.041841)
-  hash:jenkins                         0.050000   0.000000   0.050000 (  0.052283)
-  hash:md5                             0.090000   0.000000   0.090000 (  0.092901)
-  hash:crc                             0.040000   0.000000   0.040000 (  0.037710)
-  hash:fnv1a_32                        0.050000   0.000000   0.050000 (  0.047746)
-  hash:hsieh                           0.020000   0.000000   0.020000 (  0.020477)
-  hash:fnv1_32                         0.050000   0.000000   0.050000 (  0.046204)
-  hash:fnv1_64                         0.100000   0.000000   0.100000 (  0.106735)
-  hash:fnv1a_64                        0.060000   0.000000   0.060000 (  0.054646)
+  Loaded memcached 0.17
+  Loaded binary42-remix-stash 0.9.5
+  Loaded memcache-client 1.7.5
+  Loops is 40000
+  Stack depth is 0
+  Small value size is: 13 bytes
+  Large value size is: 4158 bytes
+
+                                            user     system      total        real
+  set:libm                              1.360000   2.120000   3.480000 (  8.952505)
+  set:libm:binary                       1.180000   2.100000   3.280000 (  7.692065)
+  set:libm:noblock                      0.590000   0.240000   0.830000 (  1.863921)
+  set:libm:noblock_binary               0.470000   0.220000   0.690000 (  1.678243)
+  set:libm:udp                          1.140000   1.150000   2.290000 (  4.835305)
+  set:ruby                             15.440000   6.330000  21.770000 ( 22.136843)
+  set:stash                             5.780000   2.040000   7.820000 ( 13.748268)
+  get:libm                              1.600000   2.000000   3.600000 (  8.112166)
+  get:libm:binary                       1.360000   2.150000   3.510000 (  7.829266)
+  get:libm:noblock                      1.820000   2.630000   4.450000 (  8.971191)
+  get:libm:noblock_binary               1.560000   2.650000   4.210000 (  8.114088)
+  get:libm:udp                          1.350000   1.140000   2.490000 (  4.878485)
+  get:ruby                             18.640000   6.370000  25.010000 ( 25.925459)
+  get:stash                             5.120000   1.990000   7.110000 ( 11.850485)
+  get-multi:libm                        1.770000   1.320000   3.090000 (  4.790793)
+  get-multi:libm:binary                 1.730000   1.740000   3.470000 (  5.655120)
+  get-multi:libm:noblock                1.820000   1.330000   3.150000 (  4.841084)
+  get-multi:libm:noblock_binary         1.740000   1.760000   3.500000 (  5.616970)
+  get-multi:libm:udp                    1.690000   0.960000   2.650000 (  3.551923)
+  get-multi:ruby                       21.380000   4.400000  25.780000 ( 26.017883)
+  append:libm                           1.500000   2.180000   3.680000 ( 14.658051)
+  append:libm:binary                    1.300000   2.110000   3.410000 ( 13.626305)
+  append:libm:noblock                   1.850000   2.870000   4.720000 ( 45.167145)
+  append:libm:noblock_binary            1.640000   2.870000   4.510000 ( 44.614596)
+  append:libm:udp                       1.260000   1.170000   2.430000 ( 11.556293)
+  append:ruby                          16.770000   7.310000  24.080000 ( 29.525815)
+  delete:libm                           1.890000   2.080000   3.970000 (  8.368548)
+  delete:libm:binary                    1.730000   2.090000   3.820000 (  7.799952)
+  delete:libm:noblock                   0.850000   0.890000   1.740000 (  2.530108)
+  delete:libm:noblock_binary            0.710000   0.780000   1.490000 (  2.390600)
+  delete:libm:udp                       1.700000   1.310000   3.010000 (  6.508360)
+  delete:ruby                          15.670000   6.330000  22.000000 ( 22.226087)
+  delete:stash                          4.970000   2.010000   6.980000 ( 11.726916)
+  get-missing:libm                      2.070000   2.060000   4.130000 (  8.937420)
+  get-missing:libm:binary               2.010000   2.090000   4.100000 (  8.506150)
+  get-missing:libm:noblock              2.270000   2.770000   5.040000 (  9.485592)
+  get-missing:libm:noblock_binary       2.220000   2.760000   4.980000 (  9.226826)
+  get-missing:libm:udp                  1.830000   1.300000   3.130000 (  7.135699)
+  get-missing:ruby                     16.130000   6.380000  22.510000 ( 22.888698)
+  get-missing:stash                     5.030000   2.030000   7.060000 ( 11.556793)
+  append-missing:libm                   2.210000   2.070000   4.280000 ( 10.386632)
+  append-missing:libm:binary            2.000000   2.060000   4.060000 (  9.135312)
+  append-missing:libm:noblock           2.400000   2.740000   5.140000 ( 10.821778)
+  append-missing:libm:noblock_binary    2.200000   2.770000   4.970000 (  9.699192)
+  append-missing:libm:udp               1.970000   1.320000   3.290000 (  7.668878)
+  append-missing:ruby                  15.970000   6.470000  22.440000 ( 22.912466)
+  set-large:libm                        1.460000   2.210000   3.670000 (  9.517034)
+  set-large:libm:binary                 1.260000   2.270000   3.530000 (  9.098769)
+  set-large:libm:noblock                0.980000   0.890000   1.870000 (  3.304075)
+  set-large:libm:noblock_binary         0.840000   0.890000   1.730000 (  3.444305)
+  set-large:libm:udp                    1.250000   1.330000   2.580000 (  6.924254)
+  set-large:ruby                       16.960000   6.490000  23.450000 ( 23.964380)
+  get-large:libm                        2.280000   2.450000   4.730000 (  9.908532)
+  get-large:libm:binary                 2.080000   2.530000   4.610000 (  8.966637)
+  get-large:libm:noblock                2.410000   2.850000   5.260000 ( 11.066391)
+  get-large:libm:noblock_binary         2.200000   2.910000   5.110000 ( 10.328922)
+  get-large:libm:udp                    2.010000   1.430000   3.440000 (  6.679192)
+  get-large:ruby                       21.790000   7.370000  29.160000 ( 29.578987)
+  get-large:stash                       5.430000   2.020000   7.450000 ( 11.967011)
+  set-ruby:libm                         1.800000   1.990000   3.790000 (  9.511387)
+  set-ruby:libm:binary                  1.610000   2.000000   3.610000 (  8.502297)
+  set-ruby:libm:noblock                 0.910000   0.200000   1.110000 (  2.083001)
+  set-ruby:libm:noblock_binary          0.750000   0.210000   0.960000 (  1.895510)
+  set-ruby:libm:udp                     1.530000   1.170000   2.700000 (  6.148442)
+  set-ruby:ruby                        16.290000   6.400000  22.690000 ( 23.672254)
+  set-ruby:stash                        5.570000   2.020000   7.590000 ( 13.381661)
+  get-ruby:libm                         1.920000   1.950000   3.870000 (  9.042716)
+  get-ruby:libm:binary                  1.640000   1.980000   3.620000 (  7.987886)
+  get-ruby:libm:noblock                 2.140000   2.600000   4.740000 ( 10.280036)
+  get-ruby:libm:noblock_binary          1.870000   2.590000   4.460000 (  9.213013)
+  get-ruby:libm:udp                     1.660000   1.170000   2.830000 (  5.762381)
+  get-ruby:ruby                        19.760000   6.500000  26.260000 ( 27.573109)
+  get-ruby:stash                        5.480000   2.010000   7.490000 ( 12.349059)
+  set-ruby-large:libm                  33.820000   2.340000  36.160000 ( 43.061537)
+  set-ruby-large:libm:binary           33.430000   2.260000  35.690000 ( 41.940845)
+  set-ruby-large:libm:noblock          34.170000   0.930000  35.100000 ( 35.632694)
+  set-ruby-large:libm:noblock_binary   34.010000   0.930000  34.940000 ( 35.383141)
+  set-ruby-large:libm:udp              33.150000   1.430000  34.580000 ( 39.521448)
+  set-ruby-large:ruby                  48.830000   6.560000  55.390000 ( 55.750071)
+  set-ruby-large:stash                 38.660000   2.230000  40.890000 ( 46.957838)
+  get-ruby-large:libm                  23.570000   2.340000  25.910000 ( 32.166590)
+  get-ruby-large:libm:binary           23.420000   2.510000  25.930000 ( 31.953854)
+  get-ruby-large:libm:noblock          23.840000   3.040000  26.880000 ( 32.919639)
+  get-ruby-large:libm:noblock_binary   23.570000   2.970000  26.540000 ( 32.210027)
+  get-ruby-large:libm:udp              23.210000   1.460000  24.670000 ( 29.284808)
+  get-ruby-large:ruby                  41.170000   7.560000  48.730000 ( 49.507358)
+  get-ruby-large:stash                 25.760000   2.540000  28.300000 ( 33.998493)
+  hash:fnv1a_64                         0.240000   0.000000   0.240000 (  0.247813)
+  hash:murmur                           0.190000   0.000000   0.190000 (  0.193039)
+  hash:default                          0.220000   0.000000   0.220000 (  0.216573)
+  hash:jenkins                          0.220000   0.000000   0.220000 (  0.222694)
+  hash:md5                              0.390000   0.000000   0.390000 (  0.395159)
+  hash:crc                              0.210000   0.000000   0.210000 (  0.216457)
+  hash:hsieh                            0.100000   0.000000   0.100000 (  0.104386)
+  hash:fnv1_32                          0.220000   0.000000   0.220000 (  0.216769)
+  hash:fnv1a_32                         0.230000   0.000000   0.230000 (  0.237016)
+  hash:fnv1_64                          0.450000   0.010000   0.460000 (  0.454704)
+
 </diff>
      <filename>BENCHMARKS</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 
-v0.17. Update to libmemcached 0.32. Snow Leopard changed its Darwin flag (various). Update benchmarks to use the binary protocol. Add set_servers= accessor for compatibility (defunkt).
+v0.17. Update to libmemcached 0.32. Update Darwin version string for Snow Leopard final. Improve benchmarks. Add Memcached::Rails#append and #prepend, alias all original Memcached methods to _orig, and add set_servers= accessor for compatibility.
 
 v0.16.3. Optimize append/prepend on miss.
 </diff>
      <filename>CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -78,7 +78,7 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
 
 =end
 
-  def initialize(servers, opts = {})
+  def initialize(servers = &quot;localhost:11211&quot;, opts = {})
     @struct = Lib::MemcachedSt.new
     Lib.memcached_create(@struct)
 
@@ -126,6 +126,31 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
     end
   end
 
+  # Set the server list.
+  # FIXME Does not necessarily free any existing server structs.
+  def set_servers(servers)
+    Array(servers).each_with_index do |server, index|
+      # Socket
+      if server.is_a?(String) and File.socket?(server)
+        args = [@struct, server, options[:default_weight].to_i]
+        check_return_code(Lib.memcached_server_add_unix_socket_with_weight(*args))
+      # Network
+      elsif server.is_a?(String) and server =~ /^[\w\d\.-]+(:\d{1,5}){0,2}$/
+        host, port, weight = server.split(&quot;:&quot;)
+        args = [@struct, host, port.to_i, (weight || options[:default_weight]).to_i]                
+        if options[:use_udp] #
+          check_return_code(Lib.memcached_server_add_udp_with_weight(*args))
+        else
+          check_return_code(Lib.memcached_server_add_with_weight(*args))
+        end
+      else
+        raise ArgumentError, &quot;Servers must be either in the format 'host:port[:weight]' (e.g., 'localhost:11211' or  'localhost:11211:10') for a network server, or a valid path to a Unix domain socket (e.g., /var/run/memcached).&quot;
+      end
+    end
+    # For inspect
+    @servers = send(:servers)
+  end
+
   # Return the array of server strings used to configure this instance.
   def servers
     server_structs.map do |server|
@@ -427,30 +452,6 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
     inspect_server(server) if server
   end
 
-  # Set the servers on the struct.
-  def set_servers(servers)
-    Array(servers).each_with_index do |server, index|
-      # Socket
-      if server.is_a?(String) and File.socket?(server)
-        args = [@struct, server, options[:default_weight].to_i]
-        check_return_code(Lib.memcached_server_add_unix_socket_with_weight(*args))
-      # Network
-      elsif server.is_a?(String) and server =~ /^[\w\d\.-]+(:\d{1,5}){0,2}$/
-        host, port, weight = server.split(&quot;:&quot;)
-        args = [@struct, host, port.to_i, (weight || options[:default_weight]).to_i]                
-        if options[:use_udp] #
-          check_return_code(Lib.memcached_server_add_udp_with_weight(*args))
-        else
-          check_return_code(Lib.memcached_server_add_with_weight(*args))
-        end
-      else
-        raise ArgumentError, &quot;Servers must be either in the format 'host:port[:weight]' (e.g., 'localhost:11211' or  'localhost:11211:10') for a network server, or a valid path to a Unix domain socket (e.g., /var/run/memcached).&quot;
-      end
-    end
-    # For inspect
-    @servers = send(:servers)
-  end
-
   # Set the behaviors on the struct from the current options.
   def set_behaviors
     BEHAVIORS.keys.each do |behavior|</diff>
      <filename>lib/memcached/memcached.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,14 @@
 class Memcached
 
-  alias :get_multi :get #:nodoc:
-  alias :servers= :set_servers #:nodoc:
-  public :servers=
+  (instance_methods - NilClass.instance_methods).each do |method_name|
+    eval(&quot;alias :'#{method_name}_orig' :'#{method_name}'&quot;)
+  end
 
   # A legacy compatibility wrapper for the Memcached class. It has basic compatibility with the &lt;b&gt;memcache-client&lt;/b&gt; API.
   class Rails &lt; ::Memcached
-    
-    DEFAULTS = {}
-         
+
+    alias :servers= :set_servers
+
     # See Memcached#new for details.
     def initialize(*args)
       opts = args.last.is_a?(Hash) ? args.pop : {}
@@ -17,10 +17,10 @@ class Memcached
       ).flatten.compact
 
       opts[:prefix_key] ||= opts[:namespace]
-      super(servers, DEFAULTS.merge(opts))      
+      super(servers, opts)
     end
-    
-    # Wraps Memcached#get so that it doesn't raise. This has the side-effect of preventing you from 
+
+    # Wraps Memcached#get so that it doesn't raise. This has the side-effect of preventing you from
     # storing &lt;tt&gt;nil&lt;/tt&gt; values.
     def get(key, raw=false)
       super(key, !raw)
@@ -30,56 +30,68 @@ class Memcached
     # Wraps Memcached#cas so that it doesn't raise. Doesn't set anything if no value is present.
     def cas(key, ttl=@default_ttl, raw=false, &amp;block)
       super(key, ttl, !raw, &amp;block)
-    rescue NotFound    
+    rescue NotFound
     end
-    
-    alias :compare_and_swap :cas    
-    
+
+    alias :compare_and_swap :cas
+
     # Wraps Memcached#get.
     def get_multi(keys, raw=false)
-      super(keys, !raw)
+      get_orig(keys, !raw)
     end
-    
+
     # Wraps Memcached#set.
     def set(key, value, ttl=@default_ttl, raw=false)
       super(key, value, ttl, !raw)
     end
 
-    # Wraps Memcached#add so that it doesn't raise. 
+    # Wraps Memcached#add so that it doesn't raise.
     def add(key, value, ttl=@default_ttl, raw=false)
       super(key, value, ttl, !raw)
       true
     rescue NotStored
-      false    
+      false
     end
-    
-    # Wraps Memcached#delete so that it doesn't raise. 
+
+    # Wraps Memcached#delete so that it doesn't raise.
     def delete(key)
       super
     rescue NotFound
     end
-    
-    # Wraps Memcached#incr so that it doesn't raise. 
+
+    # Wraps Memcached#incr so that it doesn't raise.
     def incr(*args)
       super
     rescue NotFound
     end
 
-    # Wraps Memcached#decr so that it doesn't raise. 
+    # Wraps Memcached#decr so that it doesn't raise.
     def decr(*args)
       super
     rescue NotFound
     end
-    
+
+    # Wraps Memcached#append so that it doesn't raise.
+    def append(*args)
+      super
+    rescue NotStored
+    end
+
+    # Wraps Memcached#prepend so that it doesn't raise.
+    def prepend(*args)
+      super
+    rescue NotStored
+    end
+
     # Namespace accessor.
     def namespace
       options[:prefix_key]
     end
-    
+
     alias :flush_all :flush
 
     alias :&quot;[]&quot; :get
-    alias :&quot;[]=&quot; :set    
-    
+    alias :&quot;[]=&quot; :set
+
   end
 end
\ No newline at end of file</diff>
      <filename>lib/memcached/rails.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,439 +12,198 @@ begin; require 'memory'; rescue LoadError; end
 puts `uname -a`
 puts &quot;Ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}&quot;
 
-[ [&quot;memcached&quot;, &quot;memcached&quot;]], 
-  [&quot;binary42-remix-stash&quot;, &quot;remix-stash&quot;]], 
+[ [&quot;memcached&quot;, &quot;memcached&quot;], 
+  [&quot;binary42-remix-stash&quot;, &quot;remix/stash&quot;], 
   # [&quot;astro-remcached&quot;, &quot;remcached&quot;], # Clobbers the &quot;Memcached&quot; constant
   [&quot;memcache-client&quot;, &quot;memcache&quot;]].each do |gem_name, requirement|
   require requirement
   gem gem_name
-  puts &quot;Loaded #{$1} #{Gem.loaded_specs[gem_name].version.to_s rescue nil}&quot;
+  puts &quot;Loaded #{gem_name} #{Gem.loaded_specs[gem_name].version.to_s rescue nil}&quot;
+end
+
+class Remix::Stash
+  # Remix::Stash API doesn't let you set servers
+  @@clusters = {:default =&gt; Remix::Stash::Cluster.new(['127.0.0.1:43042', '127.0.0.1:43043'])}
 end
 
 class Bench
 
-  def initialize(loops, recursion = 0)
-    @loops = loops
-    @recursion = recursion
-    puts &quot;Recursion level is #{@recursion}&quot;
+  def initialize(loops = nil, stack_depth = nil)
+    @loops = (loops || 20000).to_i
+    @stack_depth = (stack_depth || 0).to_i
     
-    # We'll use a simple @value to try to avoid spending time in Marshal,
-    # which is a constant penalty that both clients have to pay
-    @value = []
-    @marshalled = Marshal.dump(@value)
+    puts &quot;Loops is #{@loops}&quot;
+    puts &quot;Stack depth is #{@stack_depth}&quot;
+        
+    @m_value = Marshal.dump(
+      @small_value = [&quot;testing&quot;])    
+    @m_large_value = Marshal.dump(
+      @large_value = [{&quot;test&quot; =&gt; &quot;1&quot;, &quot;test2&quot; =&gt; &quot;2&quot;, Object.new =&gt; &quot;3&quot;, 4 =&gt; 4, &quot;test5&quot; =&gt; 2**65}] * 2048)
+
+    puts &quot;Small value size is: #{@m_value.size} bytes&quot;
+    puts &quot;Large value size is: #{@m_large_value.size} bytes&quot;
+
+    @keys = [
+      @k1 = &quot;Short&quot;,
+      @k2 = &quot;Sym1-2-3::45&quot; * 8,
+      @k3 = &quot;Long&quot; * 40,
+      @k4 = &quot;Medium&quot; * 8,
+      @k5 = &quot;Medium2&quot; * 8,
+      @k6 = &quot;Long3&quot; * 40]
     
-    @ccache_networked = Memcached.new(
-      ['127.0.0.1:43042', '127.0.0.1:43043'],
-      {:buffer_requests =&gt; false, :no_block =&gt; false, :namespace =&gt; &quot;namespace&quot;})
-    @ccache_noblock_networked = Memcached.new(
-      ['127.0.0.1:43042', '127.0.0.1:43043'],
-      {:no_block =&gt; true, :buffer_requests =&gt; true, :namespace =&gt; &quot;namespace&quot;})
-    @ccache_unix = Memcached.new(
-      [&quot;#{UNIX_SOCKET_NAME}0&quot;,&quot;#{UNIX_SOCKET_NAME}1&quot;],
-      {:buffer_requests =&gt; false, :no_block =&gt; false, :namespace =&gt; &quot;namespace&quot;})
-    @ccache_networked_binary = Memcached.new(
-      ['127.0.0.1:43042', '127.0.0.1:43043'],
-      {:buffer_requests =&gt; false, :no_block =&gt; false, :namespace =&gt; &quot;namespace&quot;, :binary_protocol =&gt; true})
-    @ccache_noblock_networked_binary = Memcached.new(
-      ['127.0.0.1:43042', '127.0.0.1:43043'],
-      {:no_block =&gt; true, :buffer_requests =&gt; true, :namespace =&gt; &quot;namespace&quot;, :binary_protocol =&gt; true})
-      
-    @rcache = MemCache.new(
-      ['127.0.0.1:43042', '127.0.0.1:43043']
-      {:namespace =&gt; &quot;namespace&quot;})
-      
-    # API doesn't let you set servers...what?
-    Remix::Stash.class_variable_get(&quot;@@clusters&quot;)[:default] = 
-      Remix::Stash::Cluster.new(['127.0.0.1:43042', '127.0.0.1:43043'])
-    @rstash = Remix::Stash.new(:root)
+    reset_servers
+    reset_clients
     
-    @ecache = Remcached
+    Benchmark.bm(36) do |x| 
+      @benchmark = x 
+    end
+  end
 
-    
-    @key1 = &quot;Short&quot;
-    @key2 = &quot;Sym1-2-3::45&quot;*8
-    @key3 = &quot;Long&quot;*40
-    @key4 = &quot;Medium&quot;*8
-    @key5 = &quot;Medium2&quot;*8 
-    @key6 = &quot;Long3&quot;*40 
-    
+  def run(level = @stack_depth)
+    level &gt; 0 ? run(level - 1) : run_without_recursion
+  end
+  
+  private
+  
+  def reset_servers
     system(&quot;ruby #{HERE}/../setup.rb&quot;)
     sleep(1)
   end
-
-  def run(level = @recursion)
-    level &gt; 0 ? run(level - 1) : benchmark
+  
+  def reset_clients
+    @clients = {
+       &quot;libm&quot; =&gt; Memcached::Rails.new(
+         ['127.0.0.1:43042', '127.0.0.1:43043'],
+         :buffer_requests =&gt; false, :no_block =&gt; false, :namespace =&gt; &quot;namespace&quot;),
+       &quot;libm:noblock&quot; =&gt; Memcached::Rails.new(
+         ['127.0.0.1:43042', '127.0.0.1:43043'],
+         :no_block =&gt; true, :buffer_requests =&gt; true, :namespace =&gt; &quot;namespace&quot;),
+       &quot;libm:udp&quot; =&gt; Memcached::Rails.new(
+         [&quot;#{UNIX_SOCKET_NAME}0&quot;, &quot;#{UNIX_SOCKET_NAME}1&quot;],
+         :buffer_requests =&gt; false, :no_block =&gt; false, :namespace =&gt; &quot;namespace&quot;),
+       &quot;libm:binary&quot; =&gt; Memcached::Rails.new(
+         ['127.0.0.1:43042', '127.0.0.1:43043'],
+         :buffer_requests =&gt; false, :no_block =&gt; false, :namespace =&gt; &quot;namespace&quot;, :binary_protocol =&gt; true),
+       &quot;libm:noblock_binary&quot; =&gt; Memcached::Rails.new(
+         ['127.0.0.1:43042', '127.0.0.1:43043'],
+         :no_block =&gt; true, :buffer_requests =&gt; true, :namespace =&gt; &quot;namespace&quot;, :binary_protocol =&gt; true),
+       &quot;ruby&quot; =&gt; MemCache.new(['127.0.0.1:43042', '127.0.0.1:43043'], :namespace =&gt; &quot;namespace&quot;),
+       &quot;stash&quot; =&gt; Remix::Stash.new(:root)}
   end
   
-  private
   
-  def benchmark(clients, name)
-    clients.each do |client|
-    
+  def benchmark_clients(test_name, clients = @clients)
+    clients.keys.sort.each do |client_name|
+      next if client_name == &quot;stash&quot; and test_name == &quot;set-large&quot; # Don't let stash break the world
+      client = clients[client_name]
+      begin
+        yield client
+        @benchmark.report(&quot;#{test_name}:#{client_name}&quot;) { @loops.times { yield client } }
+      rescue =&gt; e
+        # puts &quot;#{test_name}:#{client_name} =&gt; #{e.class}&quot;
+        # reset_clients
+      end
     end
   end
   
-  def benchmark    
-    Benchmark.bm(35) do |x|
-    
-      if defined? Memcached
-        @m = Memcached.new(
-        @opts_networked[0],
-        @opts_networked[1].merge(:no_block =&gt; true, :buffer_requests =&gt; true)
-        )
-        x.report(&quot;set:plain:noblock:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.set @key1, @marshalled, 0, false
-            @m.set @key2, @marshalled, 0, false
-            @m.set @key3, @marshalled, 0, false
-          end
-        end
-        @m = Memcached.new(
-        @opt_unix[0],
-        @opt_unix[1].merge(:no_block =&gt; true, :buffer_requests =&gt; true)
-        )
-        x.report(&quot;set:plain:noblock:memcached:uds&quot;) do
-          @loops.times do
-            @m.set @key1, @marshalled, 0, false
-            @m.set @key2, @marshalled, 0, false
-            @m.set @key3, @marshalled, 0, false
-          end
-        end
-        @m = Memcached.new(*@opts_networked)
-        x.report(&quot;set:plain:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.set @key1, @marshalled, 0, false
-            @m.set @key2, @marshalled, 0, false
-            @m.set @key3, @marshalled, 0, false
-          end
-        end # if false
-        @m = Memcached.new(*@opt_unix)
-        x.report(&quot;set:plain:memcached:uds&quot;) do
-          @loops.times do
-            @m.set @key1, @marshalled, 0, false
-            @m.set @key2, @marshalled, 0, false
-            @m.set @key3, @marshalled, 0, false
-          end
-        end
-      end
-      if defined? MemCache
-        @m = MemCache.new(*@opts_networked)
-        x.report(&quot;set:plain:memcache-client&quot;) do
-          @loops.times do
-            @m.set @key1, @marshalled, 0, true
-            @m.set @key2, @marshalled, 0, true
-            @m.set @key3, @marshalled, 0, true
-          end
-        end
+  def benchmark_hashes(hashes, test_name)
+    hashes.each do |hash_name, int|
+      @m = Memcached::Rails.new(:hash =&gt; hash_name)
+      @benchmark.report(&quot;#{test_name}:#{hash_name}&quot;) do
+        @loops.times { yield int }
       end
+    end  
+  end
+  
+  def run_without_recursion
+    benchmark_clients(&quot;set&quot;) do |c|
+      c.set @k1, @m_value, 0, true
+      c.set @k2, @m_value, 0, true
+      c.set @k3, @m_value, 0, true
+    end
+
+    benchmark_clients(&quot;get&quot;) do |c|
+      c.get @k1, true
+      c.get @k2, true
+      c.get @k3, true
+    end
     
-      if defined? Memcached
-        @m = Memcached.new(
-        @opts_networked[0],
-        @opts_networked[1].merge(:no_block =&gt; true, :buffer_requests =&gt; true)
-        )
-        x.report(&quot;set:ruby:noblock:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.set @key2, @value
-            @m.set @key3, @value
-          end
-        end
-        @m = Memcached.new(
-        @opt_unix[0],
-        @opt_unix[1].merge(:no_block =&gt; true, :buffer_requests =&gt; true)
-        )
-        x.report(&quot;set:ruby:noblock:memcached:uds&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.set @key2, @value
-            @m.set @key3, @value
-          end
-        end
-        @m = Memcached.new(*@opts_networked)
-        x.report(&quot;set:ruby:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.set @key2, @value
-            @m.set @key3, @value
-          end
-        end # if false
-        @m = Memcached.new(*@opt_unix)
-        x.report(&quot;set:ruby:memcached:uds&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.set @key2, @value
-            @m.set @key3, @value
-          end
-        end
-      end
-      if defined? MemCache
-        @m = MemCache.new(*@opts_networked)
-        x.report(&quot;set:ruby:memcache-client&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.set @key2, @value
-            @m.set @key3, @value
-          end
-        end
-      end
+    benchmark_clients(&quot;get-multi&quot;) do |c|
+      c.get_multi @keys, true
+    end
     
-      if defined? Memcached
-        @m = Memcached.new(*@opts_networked)
-        x.report(&quot;get:plain:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.get @key1, false
-            @m.get @key2, false
-            @m.get @key3, false
-          end
-        end
-        @m = Memcached.new(*@opt_unix)
-        x.report(&quot;get:plain:memcached:uds&quot;) do
-          @loops.times do
-            @m.get @key1, false
-            @m.get @key2, false
-            @m.get @key3, false
-          end
-        end
-      end
-      if defined? MemCache
-        @m = MemCache.new(*@opts_networked)
-        x.report(&quot;get:plain:memcache-client&quot;) do
-          @loops.times do
-            @m.get @key1, true
-            @m.get @key2, true
-            @m.get @key3, true
-          end
-        end
-      end
+    benchmark_clients(&quot;append&quot;) do |c|
+      c.append @k1, @m_value
+      c.append @k2, @m_value
+      c.append @k3, @m_value
+    end    
     
-      if defined? Memcached
-        @m = Memcached.new(*@opts_networked)
-        x.report(&quot;get:ruby:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.get @key1
-            @m.get @key2
-            @m.get @key3
-          end
-        end
-        @m = Memcached.new(*@opt_unix)
-        x.report(&quot;get:ruby:memcached:uds&quot;) do
-          @loops.times do
-            @m.get @key1
-            @m.get @key2
-            @m.get @key3
-          end
-        end
-      end
-      if defined? MemCache
-        @m = MemCache.new(*@opts_networked)
-        x.report(&quot;get:ruby:memcache-client&quot;) do
-          @loops.times do
-            @m.get @key1
-            @m.get @key2
-            @m.get @key3
-          end
-        end
-      end
+    benchmark_clients(&quot;delete&quot;) do |c|    
+      c.delete @k1
+      c.delete @k2
+      c.delete @k3
+    end
+    
+    benchmark_clients(&quot;get-missing&quot;) do |c|
+      c.get @k1
+      c.get @k2
+      c.get @k3
+    end
 
-      if defined? Memcached
-        @m = Memcached.new(*@opts_networked)
+    benchmark_clients(&quot;append-missing&quot;) do |c|
+      c.append @k1, @m_value
+      c.append @k2, @m_value
+      c.append @k3, @m_value
+    end
 
-        # Avoid rebuilding the array every request
-        keys = [@key1, @key2, @key3, @key4, @key5, @key6]
+    benchmark_clients(&quot;set-large&quot;) do |c|
+      c.set @k1, @m_large_value, 0, true
+      c.set @k2, @m_large_value, 0, true
+      c.set @k3, @m_large_value, 0, true
+    end
 
-        x.report(&quot;multiget:ruby:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.get keys
-          end
-        end
-        @m = Memcached.new(*@opt_unix)
+    benchmark_clients(&quot;get-large&quot;) do |c|
+      c.get @k1, true
+      c.get @k2, true
+      c.get @k3, true
+    end
 
-        # Avoid rebuilding the array every request
-        keys = [@key1, @key2, @key3, @key4, @key5, @key6]
+    benchmark_clients(&quot;set-ruby&quot;) do |c|
+      c.set @k1, @value
+      c.set @k2, @value
+      c.set @k3, @value
+    end
 
-        x.report(&quot;multiget:ruby:memcached:uds&quot;) do
-          @loops.times do
-            @m.get keys
-          end
-        end
-      end
-      if defined? MemCache
-        @m = MemCache.new(*@opts_networked)
-        x.report(&quot;multiget:ruby:memcache-client&quot;) do
-          @loops.times do
-            # We don't use the keys array because splat is slow
-            @m.get_multi @key1, @key2, @key3, @key4, @key5, @key6
-          end
-        end
-      end
-    
-      if defined? Memcached
-        @m = Memcached.new(*@opts_networked)
-        x.report(&quot;get-miss:ruby:memcached:net:bin&quot;) do
-          @loops.times do
-            begin @m.delete @key1; rescue Memcached::NotFound; end
-            begin @m.delete @key2; rescue Memcached::NotFound; end
-            begin @m.delete @key3; rescue Memcached::NotFound; end
-            begin @m.get @key1; rescue Memcached::NotFound; end
-            begin @m.get @key2; rescue Memcached::NotFound; end
-            begin @m.get @key3; rescue Memcached::NotFound; end
-          end
-        end
-        @m = Memcached.new(*@opt_unix)
-        x.report(&quot;get-miss:ruby:memcached:uds&quot;) do
-          @loops.times do
-            begin @m.delete @key1; rescue Memcached::NotFound; end
-            begin @m.delete @key2; rescue Memcached::NotFound; end
-            begin @m.delete @key3; rescue Memcached::NotFound; end
-            begin @m.get @key1; rescue Memcached::NotFound; end
-            begin @m.get @key2; rescue Memcached::NotFound; end
-            begin @m.get @key3; rescue Memcached::NotFound; end
-          end
-        end
-      end      
+    benchmark_clients(&quot;get-ruby&quot;) do |c|
+      c.get @k1
+      c.get @k2
+      c.get @k3
+    end
 
-      if defined? MemCache
-        @m = MemCache.new(*@opts_networked)
-        x.report(&quot;get-miss:ruby:memcache-client&quot;) do
-          @loops.times do
-            begin @m.delete @key1; rescue; end
-            begin @m.delete @key2; rescue; end
-            begin @m.delete @key3; rescue; end
-            begin @m.get @key1; rescue; end
-            begin @m.get @key2; rescue; end
-            begin @m.get @key3; rescue; end
-          end
-        end
-      end
-      
-      if defined? Memcached
-        @m = Memcached.new(*@opts_networked)
-        x.report(&quot;append-miss:ruby:memcached:net:bin&quot;) do
-          @loops.times do
-            begin @m.delete @key1; rescue Memcached::NotFound; end
-            begin @m.delete @key2; rescue Memcached::NotFound; end
-            begin @m.delete @key3; rescue Memcached::NotFound; end
-            begin @m.append @key1, @value; rescue Memcached::NotStored; end
-            begin @m.append @key2, @value; rescue Memcached::NotStored; end
-            begin @m.append @key3, @value; rescue Memcached::NotStored; end
-          end
-        end
-        @m = Memcached.new(*@opt_unix)
-        x.report(&quot;append-miss:ruby:memcached:uds&quot;) do
-          @loops.times do
-            begin @m.delete @key1; rescue Memcached::NotFound; end
-            begin @m.delete @key2; rescue Memcached::NotFound; end
-            begin @m.delete @key3; rescue Memcached::NotFound; end
-            begin @m.append @key1, @value; rescue Memcached::NotStored; end
-            begin @m.append @key2, @value; rescue Memcached::NotStored; end
-            begin @m.append @key3, @value; rescue Memcached::NotStored; end
-          end
-        end
-      end
-      if defined? MemCache
-        @m = MemCache.new(*@opts_networked)
-        x.report(&quot;append-miss:ruby:memcache-client&quot;) do
-          @loops.times do
-            begin @m.delete @key1; rescue; end
-            begin @m.delete @key2; rescue; end
-            begin @m.delete @key3; rescue; end
-            begin @m.append @key1, @value; rescue; end
-            begin @m.append @key2, @value; rescue; end
-            begin @m.append @key3, @value; rescue; end
-          end
-        end
-      end
-                      
-      if defined? Memcached
-        @m = Memcached.new(
-        @opts_networked[0],
-        @opts_networked[1].merge(:no_block =&gt; true, :buffer_requests =&gt; true)
-        )
-        x.report(&quot;mixed:ruby:noblock:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.get @key1
-            @m.set @key2, @value
-            @m.get @key2
-            @m.set @key3, @value
-            @m.get @key3
-          end
-        end
-        @m = Memcached.new(
-        @opt_unix[0],
-        @opt_unix[1].merge(:no_block =&gt; true, :buffer_requests =&gt; true)
-        )
-        x.report(&quot;mixed:ruby:noblock:memcached:uds&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.set @key2, @value
-            @m.set @key3, @value
-            @m.get @key1
-            @m.get @key2
-            @m.get @key3
-          end
-        end
-        @m = Memcached.new(*@opts_networked)
-        x.report(&quot;mixed:ruby:memcached:net:bin&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.get @key1
-            @m.set @key2, @value
-            @m.get @key2
-            @m.set @key3, @value
-            @m.get @key3
-          end
-        end # if false
-        @m = Memcached.new(*@opt_unix)
-        x.report(&quot;mixed:ruby:memcached:uds&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.get @key1
-            @m.set @key2, @value
-            @m.get @key2
-            @m.set @key3, @value
-            @m.get @key3
-          end
-        end # if false
-      end
-      if defined? MemCache
-        @m = MemCache.new(*@opts_networked)
-        x.report(&quot;mixed:ruby:memcache-client&quot;) do
-          @loops.times do
-            @m.set @key1, @value
-            @m.get @key1
-            @m.set @key2, @value
-            @m.get @key2
-            @m.set @key3, @value
-            @m.get @key3
-          end
-        end
-      end
-    
-      if defined? Memcached
-        unless ARGV.include? &quot;--no-hash&quot;
-          Memcached::HASH_VALUES.each do |mode, int|
-            @m = Memcached.new(@opt_unix[0], @opt_unix[1].merge(:hash =&gt; mode))
-            x.report(&quot;hash:#{mode}&quot;) do
-              @loops.times do
-                Rlibmemcached.memcached_generate_hash_rvalue(@key1, int)
-                Rlibmemcached.memcached_generate_hash_rvalue(@key2, int)
-                Rlibmemcached.memcached_generate_hash_rvalue(@key3, int)
-                Rlibmemcached.memcached_generate_hash_rvalue(@key4, int)
-                Rlibmemcached.memcached_generate_hash_rvalue(@key5, int)
-                Rlibmemcached.memcached_generate_hash_rvalue(@key6, int)
-              end
-            end
-          end
-        end
-      end
+    benchmark_clients(&quot;set-ruby-large&quot;) do |c|
+      c.set @k1, @large_value
+      c.set @k2, @large_value
+      c.set @k3, @large_value
+    end
 
-    end    
+    benchmark_clients(&quot;get-ruby-large&quot;) do |c|
+      c.get @k1
+      c.get @k2
+      c.get @k3
+    end
+     
+    benchmark_hashes(Memcached::HASH_VALUES, &quot;hash&quot;) do |i|
+      Rlibmemcached.memcached_generate_hash_rvalue(@k1, i)
+      Rlibmemcached.memcached_generate_hash_rvalue(@k2, i)
+      Rlibmemcached.memcached_generate_hash_rvalue(@k3, i)
+      Rlibmemcached.memcached_generate_hash_rvalue(@k4, i)
+      Rlibmemcached.memcached_generate_hash_rvalue(@k5, i)
+      Rlibmemcached.memcached_generate_hash_rvalue(@k6, i)    
+    end
   end
 end
 
-Bench.new((ENV[&quot;LOOPS&quot;] || 10000).to_i, (ENV[&quot;RECURSION&quot;] || 0).to_i).run
+Bench.new(ENV[&quot;LOOPS&quot;], ENV[&quot;STACK_DEPTH&quot;]).run
 
 Process.memory.each do |key, value|
   puts &quot;#{key}: #{value/1024.0}M&quot;</diff>
      <filename>test/profile/benchmark.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>1763a6346020fa8d54c96da2c30fb321fe8308e7</id>
    </parent>
  </parents>
  <author>
    <name>Evan Weaver</name>
    <email>eweaver@twitter.com</email>
  </author>
  <url>http://github.com/fauna/memcached/commit/2eeee419b713e8ffaace9fb7891be07b05c297d8</url>
  <id>2eeee419b713e8ffaace9fb7891be07b05c297d8</id>
  <committed-date>2009-09-21T19:21:46-07:00</committed-date>
  <authored-date>2009-09-21T18:48:03-07:00</authored-date>
  <message>Retool all benchmarks. Provide _orig versions of all methods in Rails helper.</message>
  <tree>9cd5b63d6df11e58a0b1899ca2a6834609e43cd8</tree>
  <committer>
    <name>Evan Weaver</name>
    <email>eweaver@twitter.com</email>
  </committer>
</commit>
