memcached-seanl 0.19.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/BENCHMARKS +120 -0
- data/CHANGELOG +77 -0
- data/LICENSE +184 -0
- data/Manifest +31 -0
- data/README +111 -0
- data/Rakefile +31 -0
- data/TODO +4 -0
- data/ext/extconf.rb +89 -0
- data/ext/libmemcached-0.32.tar.gz +0 -0
- data/ext/libmemcached.patch +270 -0
- data/ext/rlibmemcached.i +230 -0
- data/ext/rlibmemcached_wrap.c +13290 -0
- data/ext/sasl.patch +29283 -0
- data/lib/memcached/auth.rb +16 -0
- data/lib/memcached/behaviors.rb +78 -0
- data/lib/memcached/exceptions.rb +84 -0
- data/lib/memcached/integer.rb +6 -0
- data/lib/memcached/memcached.rb +649 -0
- data/lib/memcached/rails.rb +116 -0
- data/lib/memcached.rb +32 -0
- data/memcached-seanl.gemspec +32 -0
- data/memcached.gemspec +32 -0
- data/test/profile/benchmark.rb +210 -0
- data/test/profile/profile.rb +14 -0
- data/test/profile/valgrind.rb +147 -0
- data/test/setup.rb +29 -0
- data/test/teardown.rb +0 -0
- data/test/test_helper.rb +18 -0
- data/test/unit/binding_test.rb +8 -0
- data/test/unit/memcached_test.rb +1168 -0
- data/test/unit/rails_test.rb +109 -0
- metadata +117 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
class Memcached
|
|
2
|
+
|
|
3
|
+
(instance_methods - NilClass.instance_methods).each do |method_name|
|
|
4
|
+
eval("alias :'#{method_name}_orig' :'#{method_name}'")
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# A legacy compatibility wrapper for the Memcached class. It has basic compatibility with the <b>memcache-client</b> API.
|
|
8
|
+
class Rails < ::Memcached
|
|
9
|
+
|
|
10
|
+
DEFAULTS[:logger] = nil
|
|
11
|
+
|
|
12
|
+
attr_reader :logger
|
|
13
|
+
|
|
14
|
+
alias :servers= :set_servers
|
|
15
|
+
|
|
16
|
+
# See Memcached#new for details.
|
|
17
|
+
def initialize(*args)
|
|
18
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
|
19
|
+
servers = Array(
|
|
20
|
+
args.any? ? args.unshift : opts.delete(:servers)
|
|
21
|
+
).flatten.compact
|
|
22
|
+
|
|
23
|
+
opts[:prefix_key] ||= opts[:namespace]
|
|
24
|
+
@logger = opts[:logger]
|
|
25
|
+
logger.info { "memcached #{VERSION} #{servers.inspect}" } if logger
|
|
26
|
+
super(servers, opts)
|
|
27
|
+
raise RuntimeError
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def logger=(logger)
|
|
31
|
+
@logger = logger
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Wraps Memcached#get so that it doesn't raise. This has the side-effect of preventing you from
|
|
35
|
+
# storing <tt>nil</tt> values.
|
|
36
|
+
def get(key, raw=false)
|
|
37
|
+
super(key, !raw)
|
|
38
|
+
rescue NotFound
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Alternative to #get. Accepts a key and an optional options hash supporting the single option
|
|
42
|
+
# :raw.
|
|
43
|
+
def read(key, options = {})
|
|
44
|
+
get(key, options[:raw])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Wraps Memcached#cas so that it doesn't raise. Doesn't set anything if no value is present.
|
|
48
|
+
def cas(key, ttl=@default_ttl, raw=false, &block)
|
|
49
|
+
super(key, ttl, !raw, &block)
|
|
50
|
+
rescue NotFound
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
alias :compare_and_swap :cas
|
|
54
|
+
|
|
55
|
+
# Wraps Memcached#get.
|
|
56
|
+
def get_multi(keys, raw=false)
|
|
57
|
+
get_orig(keys, !raw)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Wraps Memcached#set.
|
|
61
|
+
def set(key, value, ttl=@default_ttl, raw=false)
|
|
62
|
+
super(key, value, ttl, !raw)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Alternative to #set. Accepts a key, value, and an optional options hash supporting the
|
|
66
|
+
# options :raw and :ttl.
|
|
67
|
+
def write(key, value, options = {})
|
|
68
|
+
set(key, value, options[:ttl] || @default_ttl, options[:raw])
|
|
69
|
+
true
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Wraps Memcached#add so that it doesn't raise.
|
|
73
|
+
def add(key, value, ttl=@default_ttl, raw=false)
|
|
74
|
+
super(key, value, ttl, !raw)
|
|
75
|
+
"STORED\r\n" # This causes me physical pain.
|
|
76
|
+
rescue NotStored, NotFound # Just in case of binary protocol implementation bugs
|
|
77
|
+
"NOT STORED\r\n"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Wraps Memcached#delete so that it doesn't raise.
|
|
81
|
+
def delete(key, expiry=0)
|
|
82
|
+
super(key)
|
|
83
|
+
rescue NotFound
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Wraps Memcached#incr so that it doesn't raise.
|
|
87
|
+
def incr(*args)
|
|
88
|
+
super
|
|
89
|
+
rescue NotFound
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Wraps Memcached#decr so that it doesn't raise.
|
|
93
|
+
def decr(*args)
|
|
94
|
+
super
|
|
95
|
+
rescue NotFound
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Wraps Memcached#append so that it doesn't raise.
|
|
99
|
+
def append(*args)
|
|
100
|
+
super
|
|
101
|
+
rescue NotStored, NotFound
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Wraps Memcached#prepend so that it doesn't raise.
|
|
105
|
+
def prepend(*args)
|
|
106
|
+
super
|
|
107
|
+
rescue NotStored, NotFound
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
alias :flush_all :flush
|
|
111
|
+
|
|
112
|
+
alias :"[]" :get
|
|
113
|
+
alias :"[]=" :set
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
end
|
data/lib/memcached.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
=begin rdoc
|
|
3
|
+
The generated SWIG module for accessing libmemcached's C API.
|
|
4
|
+
|
|
5
|
+
Includes the full set of libmemcached static methods (as defined in <tt>$INCLUDE_PATH/libmemcached/memcached.h</tt>), and classes for the available structs:
|
|
6
|
+
|
|
7
|
+
* <b>Rlibmemcached::MemcachedResultSt</b>
|
|
8
|
+
* <b>Rlibmemcached::MemcachedServerSt</b>
|
|
9
|
+
* <b>Rlibmemcached::MemcachedSt</b>
|
|
10
|
+
* <b>Rlibmemcached::MemcachedStatSt</b>
|
|
11
|
+
* <b>Rlibmemcached::MemcachedStringSt</b>
|
|
12
|
+
|
|
13
|
+
A number of SWIG typemaps and C helper methods are also defined in <tt>ext/libmemcached.i</tt>.
|
|
14
|
+
|
|
15
|
+
=end
|
|
16
|
+
module Rlibmemcached
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
require 'rlibmemcached'
|
|
20
|
+
|
|
21
|
+
class Memcached
|
|
22
|
+
Lib = Rlibmemcached
|
|
23
|
+
raise "libmemcached 0.32 required; you somehow linked to #{Lib.memcached_lib_version}." unless "0.32" == Lib.memcached_lib_version
|
|
24
|
+
VERSION = File.read("#{File.dirname(__FILE__)}/../CHANGELOG")[/v([\d\.]+)\./, 1]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
require 'memcached/integer'
|
|
28
|
+
require 'memcached/exceptions'
|
|
29
|
+
require 'memcached/behaviors'
|
|
30
|
+
require 'memcached/auth'
|
|
31
|
+
require 'memcached/memcached'
|
|
32
|
+
require 'memcached/rails'
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = %q{memcached-seanl}
|
|
5
|
+
s.version = "0.19.5.1"
|
|
6
|
+
|
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
|
8
|
+
s.authors = ["Sean Lynch"]
|
|
9
|
+
s.date = %q{2010-05-24}
|
|
10
|
+
s.description = %q{An interface to the libmemcached C client.}
|
|
11
|
+
s.email = %q{}
|
|
12
|
+
s.extensions = ["ext/extconf.rb"]
|
|
13
|
+
s.extra_rdoc_files = ["BENCHMARKS", "CHANGELOG", "LICENSE", "README", "TODO", "lib/memcached.rb", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb"]
|
|
14
|
+
s.files = ["BENCHMARKS", "CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "TODO", "ext/extconf.rb", "ext/libmemcached-0.32.tar.gz", "ext/libmemcached.patch", "ext/rlibmemcached.i", "ext/rlibmemcached_wrap.c", "ext/sasl.patch", "lib/memcached.rb", "lib/memcached/auth.rb", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "memcached-seanl.gemspec", "memcached.gemspec", "test/profile/benchmark.rb", "test/profile/profile.rb", "test/profile/valgrind.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb"]
|
|
15
|
+
s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/memcached/}
|
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Memcached-seanl", "--main", "README"]
|
|
17
|
+
s.require_paths = ["lib", "ext"]
|
|
18
|
+
s.rubyforge_project = %q{fauna}
|
|
19
|
+
s.rubygems_version = %q{1.3.7}
|
|
20
|
+
s.summary = %q{An interface to the libmemcached C client.}
|
|
21
|
+
s.test_files = ["test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb"]
|
|
22
|
+
|
|
23
|
+
if s.respond_to? :specification_version then
|
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
25
|
+
s.specification_version = 3
|
|
26
|
+
|
|
27
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
28
|
+
else
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
end
|
|
32
|
+
end
|
data/memcached.gemspec
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = %q{memcached}
|
|
5
|
+
s.version = "0.19.5"
|
|
6
|
+
|
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
|
8
|
+
s.authors = ["Evan Weaver"]
|
|
9
|
+
s.date = %q{2010-05-24}
|
|
10
|
+
s.description = %q{An interface to the libmemcached C client.}
|
|
11
|
+
s.email = %q{}
|
|
12
|
+
s.extensions = ["ext/extconf.rb"]
|
|
13
|
+
s.extra_rdoc_files = ["BENCHMARKS", "CHANGELOG", "LICENSE", "README", "TODO", "lib/memcached.rb", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb"]
|
|
14
|
+
s.files = ["BENCHMARKS", "CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "TODO", "ext/extconf.rb", "ext/libmemcached-0.32.tar.gz", "ext/libmemcached.patch", "ext/rlibmemcached.i", "ext/rlibmemcached_wrap.c", "ext/sasl.patch", "lib/memcached.rb", "lib/memcached/auth.rb", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "test/profile/benchmark.rb", "test/profile/profile.rb", "test/profile/valgrind.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb", "memcached.gemspec"]
|
|
15
|
+
s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/memcached/}
|
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Memcached", "--main", "README"]
|
|
17
|
+
s.require_paths = ["lib", "ext"]
|
|
18
|
+
s.rubyforge_project = %q{fauna}
|
|
19
|
+
s.rubygems_version = %q{1.3.5}
|
|
20
|
+
s.summary = %q{An interface to the libmemcached C client.}
|
|
21
|
+
s.test_files = ["test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb"]
|
|
22
|
+
|
|
23
|
+
if s.respond_to? :specification_version then
|
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
25
|
+
s.specification_version = 3
|
|
26
|
+
|
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
28
|
+
else
|
|
29
|
+
end
|
|
30
|
+
else
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
|
|
2
|
+
HERE = File.dirname(__FILE__)
|
|
3
|
+
$LOAD_PATH << "#{HERE}/../../lib/"
|
|
4
|
+
UNIX_SOCKET_NAME = File.join(ENV['TMPDIR']||'/tmp','memcached')
|
|
5
|
+
|
|
6
|
+
require 'memcached'
|
|
7
|
+
require 'benchmark'
|
|
8
|
+
require 'rubygems'
|
|
9
|
+
require 'ruby-debug' if ENV['DEBUG']
|
|
10
|
+
begin; require 'memory'; rescue LoadError; end
|
|
11
|
+
|
|
12
|
+
puts `uname -a`
|
|
13
|
+
puts "Ruby #{RUBY_VERSION}p#{RUBY_PATCHLEVEL}"
|
|
14
|
+
|
|
15
|
+
[ ["memcached", "memcached"],
|
|
16
|
+
["binary42-remix-stash", "remix/stash"],
|
|
17
|
+
# ["astro-remcached", "remcached"], # Clobbers the "Memcached" constant
|
|
18
|
+
["memcache-client", "memcache"]].each do |gem_name, requirement|
|
|
19
|
+
require requirement
|
|
20
|
+
gem gem_name
|
|
21
|
+
puts "Loaded #{gem_name} #{Gem.loaded_specs[gem_name].version.to_s rescue nil}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class Remix::Stash
|
|
25
|
+
# Remix::Stash API doesn't let you set servers
|
|
26
|
+
@@clusters = {:default => Remix::Stash::Cluster.new(['127.0.0.1:43042', '127.0.0.1:43043'])}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class Bench
|
|
30
|
+
|
|
31
|
+
def initialize(loops = nil, stack_depth = nil)
|
|
32
|
+
@loops = (loops || 20000).to_i
|
|
33
|
+
@stack_depth = (stack_depth || 0).to_i
|
|
34
|
+
|
|
35
|
+
puts "Loops is #{@loops}"
|
|
36
|
+
puts "Stack depth is #{@stack_depth}"
|
|
37
|
+
|
|
38
|
+
@m_value = Marshal.dump(
|
|
39
|
+
@small_value = ["testing"])
|
|
40
|
+
@m_large_value = Marshal.dump(
|
|
41
|
+
@large_value = [{"test" => "1", "test2" => "2", Object.new => "3", 4 => 4, "test5" => 2**65}] * 2048)
|
|
42
|
+
|
|
43
|
+
puts "Small value size is: #{@m_value.size} bytes"
|
|
44
|
+
puts "Large value size is: #{@m_large_value.size} bytes"
|
|
45
|
+
|
|
46
|
+
@keys = [
|
|
47
|
+
@k1 = "Short",
|
|
48
|
+
@k2 = "Sym1-2-3::45" * 8,
|
|
49
|
+
@k3 = "Long" * 40,
|
|
50
|
+
@k4 = "Medium" * 8,
|
|
51
|
+
@k5 = "Medium2" * 8,
|
|
52
|
+
@k6 = "Long3" * 40]
|
|
53
|
+
|
|
54
|
+
reset_servers
|
|
55
|
+
reset_clients
|
|
56
|
+
|
|
57
|
+
Benchmark.bm(36) do |x|
|
|
58
|
+
@benchmark = x
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def run(level = @stack_depth)
|
|
63
|
+
level > 0 ? run(level - 1) : run_without_recursion
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def reset_servers
|
|
69
|
+
system("ruby #{HERE}/../setup.rb")
|
|
70
|
+
sleep(1)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def reset_clients
|
|
74
|
+
@clients = {
|
|
75
|
+
"libm" => Memcached::Rails.new(
|
|
76
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
|
77
|
+
:buffer_requests => false, :no_block => false, :namespace => "namespace"),
|
|
78
|
+
"libm:noblock" => Memcached::Rails.new(
|
|
79
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
|
80
|
+
:no_block => true, :buffer_requests => true, :namespace => "namespace"),
|
|
81
|
+
"libm:udp" => Memcached::Rails.new(
|
|
82
|
+
["#{UNIX_SOCKET_NAME}0", "#{UNIX_SOCKET_NAME}1"],
|
|
83
|
+
:buffer_requests => false, :no_block => false, :namespace => "namespace"),
|
|
84
|
+
"libm:binary" => Memcached::Rails.new(
|
|
85
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
|
86
|
+
:buffer_requests => false, :no_block => false, :namespace => "namespace", :binary_protocol => true),
|
|
87
|
+
"libm:noblock_binary" => Memcached::Rails.new(
|
|
88
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
|
89
|
+
:no_block => true, :buffer_requests => true, :namespace => "namespace", :binary_protocol => true),
|
|
90
|
+
"ruby" => MemCache.new(['127.0.0.1:43042', '127.0.0.1:43043'], :namespace => "namespace"),
|
|
91
|
+
"stash" => Remix::Stash.new(:root)}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def benchmark_clients(test_name, clients = @clients)
|
|
96
|
+
clients.keys.sort.each do |client_name|
|
|
97
|
+
next if client_name == "stash" and test_name == "set-large" # Don't let stash break the world
|
|
98
|
+
client = clients[client_name]
|
|
99
|
+
begin
|
|
100
|
+
yield client
|
|
101
|
+
@benchmark.report("#{test_name}:#{client_name}") { @loops.times { yield client } }
|
|
102
|
+
rescue => e
|
|
103
|
+
# puts "#{test_name}:#{client_name} => #{e.class}"
|
|
104
|
+
# reset_clients
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def benchmark_hashes(hashes, test_name)
|
|
110
|
+
hashes.each do |hash_name, int|
|
|
111
|
+
@m = Memcached::Rails.new(:hash => hash_name)
|
|
112
|
+
@benchmark.report("#{test_name}:#{hash_name}") do
|
|
113
|
+
@loops.times { yield int }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def run_without_recursion
|
|
119
|
+
benchmark_clients("set") do |c|
|
|
120
|
+
c.set @k1, @m_value, 0, true
|
|
121
|
+
c.set @k2, @m_value, 0, true
|
|
122
|
+
c.set @k3, @m_value, 0, true
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
benchmark_clients("get") do |c|
|
|
126
|
+
c.get @k1, true
|
|
127
|
+
c.get @k2, true
|
|
128
|
+
c.get @k3, true
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
benchmark_clients("get-multi") do |c|
|
|
132
|
+
c.get_multi @keys, true
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
benchmark_clients("append") do |c|
|
|
136
|
+
c.append @k1, @m_value
|
|
137
|
+
c.append @k2, @m_value
|
|
138
|
+
c.append @k3, @m_value
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
benchmark_clients("delete") do |c|
|
|
142
|
+
c.delete @k1
|
|
143
|
+
c.delete @k2
|
|
144
|
+
c.delete @k3
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
benchmark_clients("get-missing") do |c|
|
|
148
|
+
c.get @k1
|
|
149
|
+
c.get @k2
|
|
150
|
+
c.get @k3
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
benchmark_clients("append-missing") do |c|
|
|
154
|
+
c.append @k1, @m_value
|
|
155
|
+
c.append @k2, @m_value
|
|
156
|
+
c.append @k3, @m_value
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
benchmark_clients("set-large") do |c|
|
|
160
|
+
c.set @k1, @m_large_value, 0, true
|
|
161
|
+
c.set @k2, @m_large_value, 0, true
|
|
162
|
+
c.set @k3, @m_large_value, 0, true
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
benchmark_clients("get-large") do |c|
|
|
166
|
+
c.get @k1, true
|
|
167
|
+
c.get @k2, true
|
|
168
|
+
c.get @k3, true
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
benchmark_clients("set-ruby") do |c|
|
|
172
|
+
c.set @k1, @value
|
|
173
|
+
c.set @k2, @value
|
|
174
|
+
c.set @k3, @value
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
benchmark_clients("get-ruby") do |c|
|
|
178
|
+
c.get @k1
|
|
179
|
+
c.get @k2
|
|
180
|
+
c.get @k3
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
benchmark_clients("set-ruby-large") do |c|
|
|
184
|
+
c.set @k1, @large_value
|
|
185
|
+
c.set @k2, @large_value
|
|
186
|
+
c.set @k3, @large_value
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
benchmark_clients("get-ruby-large") do |c|
|
|
190
|
+
c.get @k1
|
|
191
|
+
c.get @k2
|
|
192
|
+
c.get @k3
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
benchmark_hashes(Memcached::HASH_VALUES, "hash") do |i|
|
|
196
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k1, i)
|
|
197
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k2, i)
|
|
198
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k3, i)
|
|
199
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k4, i)
|
|
200
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k5, i)
|
|
201
|
+
Rlibmemcached.memcached_generate_hash_rvalue(@k6, i)
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
Bench.new(ENV["LOOPS"], ENV["STACK_DEPTH"]).run
|
|
207
|
+
|
|
208
|
+
Process.memory.each do |key, value|
|
|
209
|
+
puts "#{key}: #{value/1024.0}M"
|
|
210
|
+
end if Process.respond_to? :memory
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
require "#{File.dirname(__FILE__)}/../setup"
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH << "#{File.dirname(__FILE__)}/../../lib/"
|
|
5
|
+
require 'rubygems'
|
|
6
|
+
require 'memcached'
|
|
7
|
+
require 'ruby-prof'
|
|
8
|
+
|
|
9
|
+
result = RubyProf.profile do
|
|
10
|
+
load "#{HERE}/profile/valgrind.rb"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
printer = RubyProf::GraphPrinter.new(result)
|
|
14
|
+
printer.print(STDOUT, 0)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
|
|
2
|
+
require "#{File.dirname(__FILE__)}/../setup"
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH << "#{File.dirname(__FILE__)}/../../lib/"
|
|
5
|
+
require 'memcached'
|
|
6
|
+
require 'rubygems'
|
|
7
|
+
|
|
8
|
+
class Worker
|
|
9
|
+
def initialize(method_name, iterations)
|
|
10
|
+
@method = method_name || 'mixed'
|
|
11
|
+
@i = (iterations || 10000).to_i
|
|
12
|
+
|
|
13
|
+
puts "*** Running #{@method.inspect} test for #{@i} loops. ***"
|
|
14
|
+
|
|
15
|
+
@key1 = "key1-"*8
|
|
16
|
+
@key2 = "key2-"*8
|
|
17
|
+
|
|
18
|
+
@value = []
|
|
19
|
+
@marshalled = Marshal.dump(@value)
|
|
20
|
+
|
|
21
|
+
@opts = [
|
|
22
|
+
["#{UNIX_SOCKET_NAME}0", "#{UNIX_SOCKET_NAME}1"],
|
|
23
|
+
{
|
|
24
|
+
:buffer_requests => false,
|
|
25
|
+
:no_block => false,
|
|
26
|
+
:namespace => "namespace"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
@cache = Memcached.new(*@opts)
|
|
30
|
+
|
|
31
|
+
@cache.set @key1, @value
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def work
|
|
35
|
+
case @method
|
|
36
|
+
when "set"
|
|
37
|
+
@i.times do
|
|
38
|
+
@cache.set @key1, @value
|
|
39
|
+
end
|
|
40
|
+
when "get"
|
|
41
|
+
@i.times do
|
|
42
|
+
@cache.get @key1
|
|
43
|
+
end
|
|
44
|
+
when "delete"
|
|
45
|
+
@i.times do
|
|
46
|
+
@cache.set @key1, @value
|
|
47
|
+
@cache.delete @key1
|
|
48
|
+
end
|
|
49
|
+
when "delete-miss"
|
|
50
|
+
@i.times do
|
|
51
|
+
@cache.delete @key1
|
|
52
|
+
end
|
|
53
|
+
when "get-miss"
|
|
54
|
+
@i.times do
|
|
55
|
+
begin
|
|
56
|
+
@cache.get @key2
|
|
57
|
+
rescue Memcached::NotFound
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
when "get-increasing"
|
|
61
|
+
one_k = "x"*1024
|
|
62
|
+
@i.times do |i|
|
|
63
|
+
@cache.set @key1, one_k*(i+1), 0, false
|
|
64
|
+
@cache.get @key1, false
|
|
65
|
+
end
|
|
66
|
+
when "get-miss-increasing"
|
|
67
|
+
@i.times do |i|
|
|
68
|
+
@cache.delete @key2 rescue nil
|
|
69
|
+
begin
|
|
70
|
+
@cache.get @key2
|
|
71
|
+
rescue Memcached::NotFound
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
when "add"
|
|
75
|
+
@i.times do
|
|
76
|
+
begin
|
|
77
|
+
@cache.delete @key1
|
|
78
|
+
rescue
|
|
79
|
+
end
|
|
80
|
+
@cache.add @key1, @value
|
|
81
|
+
end
|
|
82
|
+
when "add-present"
|
|
83
|
+
@cache.set @key1, @value
|
|
84
|
+
@i.times do
|
|
85
|
+
begin
|
|
86
|
+
@cache.add @key1, @value
|
|
87
|
+
rescue Memcached::NotStored
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
when "mixed"
|
|
91
|
+
@i.times do
|
|
92
|
+
@cache.set @key1, @value
|
|
93
|
+
@cache.get @key1
|
|
94
|
+
end
|
|
95
|
+
when "stats"
|
|
96
|
+
@i.times do
|
|
97
|
+
@cache.stats
|
|
98
|
+
end
|
|
99
|
+
when "multiget"
|
|
100
|
+
@i.times do
|
|
101
|
+
@cache.get([@key1, @key2])
|
|
102
|
+
end
|
|
103
|
+
when "clone"
|
|
104
|
+
@i.times do
|
|
105
|
+
cache = @cache.clone
|
|
106
|
+
end
|
|
107
|
+
when "reset"
|
|
108
|
+
@i.times do
|
|
109
|
+
@cache.reset
|
|
110
|
+
end
|
|
111
|
+
when "servers"
|
|
112
|
+
@i.times do
|
|
113
|
+
@cache.servers
|
|
114
|
+
end
|
|
115
|
+
when "server_by_key"
|
|
116
|
+
@i.times do
|
|
117
|
+
@cache.server_by_key(@key1)
|
|
118
|
+
end
|
|
119
|
+
else
|
|
120
|
+
raise "No such method"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
puts "*** Garbage collect. ***"
|
|
124
|
+
10.times do
|
|
125
|
+
GC.start
|
|
126
|
+
sleep 0.1
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
sts, server_sts, clients = 0, 0, 0
|
|
130
|
+
ObjectSpace.each_object(Memcached) { clients += 1 }
|
|
131
|
+
ObjectSpace.each_object(Rlibmemcached::MemcachedSt) { sts += 1 }
|
|
132
|
+
ObjectSpace.each_object(Rlibmemcached::MemcachedServerSt) { server_sts += 1 }
|
|
133
|
+
puts "*** Structs: #{sts} ***"
|
|
134
|
+
puts "*** Server structs: #{server_sts} ***"
|
|
135
|
+
puts "*** Clients: #{clients} ***"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
Worker.new(ENV['METHOD'], ENV['LOOPS']).work
|
|
140
|
+
|
|
141
|
+
begin
|
|
142
|
+
require 'memory'
|
|
143
|
+
Process.memory.each do |key, value|
|
|
144
|
+
puts "#{key}: #{value/1024.0}M"
|
|
145
|
+
end
|
|
146
|
+
rescue LoadError
|
|
147
|
+
end
|
data/test/setup.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
unless defined? UNIX_SOCKET_NAME
|
|
3
|
+
HERE = File.dirname(__FILE__)
|
|
4
|
+
UNIX_SOCKET_NAME = File.join(ENV['TMPDIR']||'/tmp','memcached')
|
|
5
|
+
|
|
6
|
+
# Kill memcached
|
|
7
|
+
system("killall -9 memcached")
|
|
8
|
+
|
|
9
|
+
# Start memcached
|
|
10
|
+
verbosity = (ENV['DEBUG'] ? "-vv" : "")
|
|
11
|
+
log = "/tmp/memcached.log"
|
|
12
|
+
system ">#{log}"
|
|
13
|
+
|
|
14
|
+
# TCP memcached
|
|
15
|
+
(43042..43046).each do |port|
|
|
16
|
+
cmd = "memcached #{verbosity} -U 0 -p #{port} >> #{log} 2>&1 &"
|
|
17
|
+
raise "'#{cmd}' failed to start" unless system(cmd)
|
|
18
|
+
end
|
|
19
|
+
# UDP memcached
|
|
20
|
+
(43052..43053).each do |port|
|
|
21
|
+
cmd = "memcached #{verbosity} -U #{port} -p 0 >> #{log} 2>&1 &"
|
|
22
|
+
raise "'#{cmd}' failed to start" unless system(cmd)
|
|
23
|
+
end
|
|
24
|
+
# Domain socket memcached
|
|
25
|
+
(0..1).each do |i|
|
|
26
|
+
cmd = "memcached -M -s #{UNIX_SOCKET_NAME}#{i} #{verbosity} >> #{log} 2>&1 &"
|
|
27
|
+
raise "'#{cmd}' failed to start" unless system(cmd)
|
|
28
|
+
end
|
|
29
|
+
end
|
data/test/teardown.rb
ADDED
|
File without changes
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
$LOAD_PATH << "#{File.dirname(__FILE__)}/../lib"
|
|
3
|
+
|
|
4
|
+
require 'rubygems'
|
|
5
|
+
require 'mocha'
|
|
6
|
+
|
|
7
|
+
if ENV['DEBUG']
|
|
8
|
+
require 'ruby-debug'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
require 'memcached'
|
|
12
|
+
require 'test/unit'
|
|
13
|
+
require 'ostruct'
|
|
14
|
+
|
|
15
|
+
UNIX_SOCKET_NAME = File.join(ENV['TMPDIR']||'/tmp','memcached') unless defined? UNIX_SOCKET_NAME
|
|
16
|
+
|
|
17
|
+
class GenericClass
|
|
18
|
+
end
|