modesty 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +13 -0
- data/Gemfile.lock +18 -0
- data/LICENSE +21 -0
- data/README.md +121 -0
- data/Rakefile +29 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/lib/modesty.rb +26 -0
- data/lib/modesty/api.rb +14 -0
- data/lib/modesty/core_ext.rb +5 -0
- data/lib/modesty/core_ext/array.rb +21 -0
- data/lib/modesty/core_ext/fixnum.rb +5 -0
- data/lib/modesty/core_ext/hash.rb +39 -0
- data/lib/modesty/core_ext/string.rb +9 -0
- data/lib/modesty/core_ext/symbol.rb +33 -0
- data/lib/modesty/datastore.rb +51 -0
- data/lib/modesty/datastore/redis.rb +180 -0
- data/lib/modesty/experiment.rb +87 -0
- data/lib/modesty/experiment/base.rb +47 -0
- data/lib/modesty/experiment/builder.rb +48 -0
- data/lib/modesty/experiment/console.rb +4 -0
- data/lib/modesty/experiment/data.rb +75 -0
- data/lib/modesty/experiment/interface.rb +29 -0
- data/lib/modesty/experiment/significance.rb +376 -0
- data/lib/modesty/experiment/stats.rb +163 -0
- data/lib/modesty/frameworks/rails.rb +27 -0
- data/lib/modesty/identity.rb +32 -0
- data/lib/modesty/load.rb +80 -0
- data/lib/modesty/load/load_experiments.rb +14 -0
- data/lib/modesty/load/load_metrics.rb +17 -0
- data/lib/modesty/metric.rb +56 -0
- data/lib/modesty/metric/base.rb +38 -0
- data/lib/modesty/metric/builder.rb +23 -0
- data/lib/modesty/metric/data.rb +133 -0
- data/modesty.gemspec +192 -0
- data/spec/core_ext_spec.rb +17 -0
- data/spec/experiment_spec.rb +239 -0
- data/spec/identity_spec.rb +161 -0
- data/spec/load_spec.rb +87 -0
- data/spec/metric_spec.rb +176 -0
- data/spec/rails_spec.rb +48 -0
- data/spec/redis_spec.rb +29 -0
- data/spec/significance_spec.rb +147 -0
- data/spec/spec.opts +1 -0
- data/test/myapp/config/modesty.yml +9 -0
- data/test/myapp/modesty/experiments/cookbook.rb +4 -0
- data/test/myapp/modesty/metrics/kitchen_metrics.rb +9 -0
- data/test/myapp/modesty/metrics/stove/burner_metrics.rb +2 -0
- data/vendor/.piston.yml +8 -0
- data/vendor/mock_redis/.gitignore +2 -0
- data/vendor/mock_redis/README +8 -0
- data/vendor/mock_redis/lib/mock_redis.rb +10 -0
- data/vendor/mock_redis/lib/mock_redis/hash.rb +61 -0
- data/vendor/mock_redis/lib/mock_redis/list.rb +6 -0
- data/vendor/mock_redis/lib/mock_redis/misc.rb +69 -0
- data/vendor/mock_redis/lib/mock_redis/set.rb +108 -0
- data/vendor/mock_redis/lib/mock_redis/string.rb +32 -0
- data/vendor/redis-rb/.gitignore +8 -0
- data/vendor/redis-rb/LICENSE +20 -0
- data/vendor/redis-rb/README.markdown +129 -0
- data/vendor/redis-rb/Rakefile +155 -0
- data/vendor/redis-rb/benchmarking/logging.rb +62 -0
- data/vendor/redis-rb/benchmarking/pipeline.rb +51 -0
- data/vendor/redis-rb/benchmarking/speed.rb +21 -0
- data/vendor/redis-rb/benchmarking/suite.rb +24 -0
- data/vendor/redis-rb/benchmarking/thread_safety.rb +38 -0
- data/vendor/redis-rb/benchmarking/worker.rb +71 -0
- data/vendor/redis-rb/examples/basic.rb +15 -0
- data/vendor/redis-rb/examples/dist_redis.rb +43 -0
- data/vendor/redis-rb/examples/incr-decr.rb +17 -0
- data/vendor/redis-rb/examples/list.rb +26 -0
- data/vendor/redis-rb/examples/pubsub.rb +31 -0
- data/vendor/redis-rb/examples/sets.rb +36 -0
- data/vendor/redis-rb/examples/unicorn/config.ru +3 -0
- data/vendor/redis-rb/examples/unicorn/unicorn.rb +20 -0
- data/vendor/redis-rb/lib/redis.rb +676 -0
- data/vendor/redis-rb/lib/redis/client.rb +201 -0
- data/vendor/redis-rb/lib/redis/compat.rb +21 -0
- data/vendor/redis-rb/lib/redis/connection.rb +134 -0
- data/vendor/redis-rb/lib/redis/distributed.rb +526 -0
- data/vendor/redis-rb/lib/redis/hash_ring.rb +131 -0
- data/vendor/redis-rb/lib/redis/pipeline.rb +13 -0
- data/vendor/redis-rb/lib/redis/subscribe.rb +79 -0
- data/vendor/redis-rb/redis.gemspec +29 -0
- data/vendor/redis-rb/test/commands_on_hashes_test.rb +46 -0
- data/vendor/redis-rb/test/commands_on_lists_test.rb +50 -0
- data/vendor/redis-rb/test/commands_on_sets_test.rb +78 -0
- data/vendor/redis-rb/test/commands_on_sorted_sets_test.rb +109 -0
- data/vendor/redis-rb/test/commands_on_strings_test.rb +70 -0
- data/vendor/redis-rb/test/commands_on_value_types_test.rb +88 -0
- data/vendor/redis-rb/test/connection_handling_test.rb +87 -0
- data/vendor/redis-rb/test/db/.gitignore +1 -0
- data/vendor/redis-rb/test/distributd_key_tags_test.rb +53 -0
- data/vendor/redis-rb/test/distributed_blocking_commands_test.rb +54 -0
- data/vendor/redis-rb/test/distributed_commands_on_hashes_test.rb +12 -0
- data/vendor/redis-rb/test/distributed_commands_on_lists_test.rb +18 -0
- data/vendor/redis-rb/test/distributed_commands_on_sets_test.rb +85 -0
- data/vendor/redis-rb/test/distributed_commands_on_strings_test.rb +50 -0
- data/vendor/redis-rb/test/distributed_commands_on_value_types_test.rb +73 -0
- data/vendor/redis-rb/test/distributed_commands_requiring_clustering_test.rb +141 -0
- data/vendor/redis-rb/test/distributed_connection_handling_test.rb +25 -0
- data/vendor/redis-rb/test/distributed_internals_test.rb +18 -0
- data/vendor/redis-rb/test/distributed_persistence_control_commands_test.rb +24 -0
- data/vendor/redis-rb/test/distributed_publish_subscribe_test.rb +90 -0
- data/vendor/redis-rb/test/distributed_remote_server_control_commands_test.rb +31 -0
- data/vendor/redis-rb/test/distributed_sorting_test.rb +21 -0
- data/vendor/redis-rb/test/distributed_test.rb +60 -0
- data/vendor/redis-rb/test/distributed_transactions_test.rb +34 -0
- data/vendor/redis-rb/test/encoding_test.rb +16 -0
- data/vendor/redis-rb/test/helper.rb +86 -0
- data/vendor/redis-rb/test/internals_test.rb +27 -0
- data/vendor/redis-rb/test/lint/hashes.rb +90 -0
- data/vendor/redis-rb/test/lint/internals.rb +53 -0
- data/vendor/redis-rb/test/lint/lists.rb +93 -0
- data/vendor/redis-rb/test/lint/sets.rb +66 -0
- data/vendor/redis-rb/test/lint/sorted_sets.rb +132 -0
- data/vendor/redis-rb/test/lint/strings.rb +98 -0
- data/vendor/redis-rb/test/lint/value_types.rb +84 -0
- data/vendor/redis-rb/test/persistence_control_commands_test.rb +22 -0
- data/vendor/redis-rb/test/pipelining_commands_test.rb +78 -0
- data/vendor/redis-rb/test/publish_subscribe_test.rb +151 -0
- data/vendor/redis-rb/test/redis_mock.rb +64 -0
- data/vendor/redis-rb/test/remote_server_control_commands_test.rb +56 -0
- data/vendor/redis-rb/test/sorting_test.rb +44 -0
- data/vendor/redis-rb/test/test.conf +8 -0
- data/vendor/redis-rb/test/thread_safety_test.rb +34 -0
- data/vendor/redis-rb/test/transactions_test.rb +91 -0
- data/vendor/redis-rb/test/unknown_commands_test.rb +14 -0
- data/vendor/redis-rb/test/url_param_test.rb +52 -0
- metadata +277 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
class MockRedis
|
2
|
+
module StringMethods
|
3
|
+
def [](key)
|
4
|
+
self.hash[key]
|
5
|
+
end
|
6
|
+
alias get []
|
7
|
+
|
8
|
+
def []=(key, value)
|
9
|
+
self.hash[key] = value.to_s
|
10
|
+
end
|
11
|
+
alias set []=
|
12
|
+
|
13
|
+
def setnx(key, value)
|
14
|
+
self.hash[key] = value.to_s unless self.hash.has_key?(key)
|
15
|
+
end
|
16
|
+
|
17
|
+
def incr(key)
|
18
|
+
self.hash[key] = (self.hash[key].to_i + 1).to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def incrby(key, value)
|
22
|
+
self.hash[key] = (self.hash[key].to_i + value).to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def mget(keys)
|
26
|
+
self.hash.values_at(*keys)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
include StringMethods
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Ezra Zygmuntowicz
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# redis-rb
|
2
|
+
|
3
|
+
A Ruby client library for the [Redis](http://code.google.com/p/redis) key-value store.
|
4
|
+
|
5
|
+
## A note about versions
|
6
|
+
|
7
|
+
Versions *1.0.x* target all versions of Redis. You have to use this one if you are using Redis < 1.2.
|
8
|
+
|
9
|
+
Version *2.0* is a big refactoring of the previous version and makes little effort to be
|
10
|
+
backwards-compatible when it shouldn't. It does not support Redis' original protocol, favoring the
|
11
|
+
new, binary-safe one. You should be using this version if you're running Redis 1.2+.
|
12
|
+
|
13
|
+
## Information about Redis
|
14
|
+
|
15
|
+
Redis is a key-value store with some interesting features:
|
16
|
+
|
17
|
+
1. It's fast.
|
18
|
+
2. Keys are strings but values are typed. Currently Redis supports strings, lists, sets, sorted sets and hashes. [Atomic operations](http://code.google.com/p/redis/wiki/CommandReference) can be done on all of these types.
|
19
|
+
|
20
|
+
See [the Redis homepage](http://code.google.com/p/redis/wiki/README) for more information.
|
21
|
+
|
22
|
+
## Getting started
|
23
|
+
|
24
|
+
You can connect to Redis by instantiating the `Redis` class:
|
25
|
+
|
26
|
+
require "redis"
|
27
|
+
|
28
|
+
redis = Redis.new
|
29
|
+
|
30
|
+
This assumes Redis was started with default values listening on `localhost`, port 6379. If you need to connect to a remote server or a different port, try:
|
31
|
+
|
32
|
+
redis = Redis.new(:host => "10.0.1.1", :port => 6380)
|
33
|
+
|
34
|
+
Once connected, you can start running commands against Redis:
|
35
|
+
|
36
|
+
>> redis.set "foo", "bar"
|
37
|
+
=> "OK"
|
38
|
+
|
39
|
+
>> redis.get "foo"
|
40
|
+
=> "bar"
|
41
|
+
|
42
|
+
>> redis.sadd "users", "albert"
|
43
|
+
=> true
|
44
|
+
|
45
|
+
>> redis.sadd "users", "bernard"
|
46
|
+
=> true
|
47
|
+
|
48
|
+
>> redis.sadd "users", "charles"
|
49
|
+
=> true
|
50
|
+
|
51
|
+
How many users?
|
52
|
+
|
53
|
+
>> redis.scard "users"
|
54
|
+
=> 3
|
55
|
+
|
56
|
+
Is `albert` a user?
|
57
|
+
|
58
|
+
>> redis.sismember "users", "albert"
|
59
|
+
=> true
|
60
|
+
|
61
|
+
Is `isabel` a user?
|
62
|
+
|
63
|
+
>> redis.sismember "users", "isabel"
|
64
|
+
=> false
|
65
|
+
|
66
|
+
Handle groups:
|
67
|
+
|
68
|
+
>> redis.sadd "admins", "albert"
|
69
|
+
=> true
|
70
|
+
|
71
|
+
>> redis.sadd "admins", "isabel"
|
72
|
+
=> true
|
73
|
+
|
74
|
+
Users who are also admins:
|
75
|
+
|
76
|
+
>> redis.sinter "users", "admins"
|
77
|
+
=> ["albert"]
|
78
|
+
|
79
|
+
Users who are not admins:
|
80
|
+
|
81
|
+
>> redis.sdiff "users", "admins"
|
82
|
+
=> ["bernard", "charles"]
|
83
|
+
|
84
|
+
Admins who are not users:
|
85
|
+
|
86
|
+
>> redis.sdiff "admins", "users"
|
87
|
+
=> ["isabel"]
|
88
|
+
|
89
|
+
All users and admins:
|
90
|
+
|
91
|
+
>> redis.sunion "admins", "users"
|
92
|
+
=> ["albert", "bernard", "charles", "isabel"]
|
93
|
+
|
94
|
+
|
95
|
+
## Storing objects
|
96
|
+
|
97
|
+
Redis only stores strings as values. If you want to store an object inside a key, you can use a serialization/deseralization mechanism like JSON:
|
98
|
+
|
99
|
+
>> redis.set "foo", [1, 2, 3].to_json
|
100
|
+
=> OK
|
101
|
+
|
102
|
+
>> JSON.parse(redis.get("foo"))
|
103
|
+
=> [1, 2, 3]
|
104
|
+
|
105
|
+
## Executing multiple commands atomically
|
106
|
+
|
107
|
+
You can use `MULTI/EXEC` to run arbitrary commands in an atomic fashion:
|
108
|
+
|
109
|
+
redis.multi do
|
110
|
+
redis.set "foo", "bar"
|
111
|
+
redis.incr "baz"
|
112
|
+
end
|
113
|
+
|
114
|
+
## Multithreaded Operation
|
115
|
+
|
116
|
+
To use redis safely in a multithreaded environment, be sure to initialize the client with :thread_safe=>true
|
117
|
+
|
118
|
+
Redis.new(:thread_safe=>true)
|
119
|
+
|
120
|
+
See the tests and benchmarks for examples.
|
121
|
+
|
122
|
+
|
123
|
+
## More info
|
124
|
+
|
125
|
+
Check the [Redis Command Reference](http://code.google.com/p/redis/wiki/CommandReference) or check the tests to find out how to use this client.
|
126
|
+
|
127
|
+
## Contributing
|
128
|
+
|
129
|
+
[Fork the project](http://github.com/ezmobius/redis-rb) and send pull requests. You can also ask for help at `#redis-rb` on Freenode.
|
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
6
|
+
require 'redis'
|
7
|
+
|
8
|
+
GEM = 'redis'
|
9
|
+
GEM_NAME = 'redis'
|
10
|
+
GEM_VERSION = Redis::VERSION
|
11
|
+
AUTHORS = ['Ezra Zygmuntowicz', 'Taylor Weibley', 'Matthew Clark', 'Brian McKinney', 'Salvatore Sanfilippo', 'Luca Guidi', 'Michel Martens', 'Damian Janowski']
|
12
|
+
EMAIL = "ez@engineyard.com"
|
13
|
+
HOMEPAGE = "http://github.com/ezmobius/redis-rb"
|
14
|
+
SUMMARY = "Ruby client library for Redis, the key value storage server"
|
15
|
+
|
16
|
+
spec = Gem::Specification.new do |s|
|
17
|
+
s.name = GEM
|
18
|
+
s.version = GEM_VERSION
|
19
|
+
s.platform = Gem::Platform::RUBY
|
20
|
+
s.has_rdoc = true
|
21
|
+
s.extra_rdoc_files = ["LICENSE"]
|
22
|
+
s.summary = SUMMARY
|
23
|
+
s.description = s.summary
|
24
|
+
s.authors = AUTHORS
|
25
|
+
s.email = EMAIL
|
26
|
+
s.homepage = HOMEPAGE
|
27
|
+
s.require_path = 'lib'
|
28
|
+
s.autorequire = GEM
|
29
|
+
s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("{lib,tasks,spec}/**/*")
|
30
|
+
end
|
31
|
+
|
32
|
+
REDIS_DIR = File.expand_path(File.join("..", "test"), __FILE__)
|
33
|
+
REDIS_CNF = File.join(REDIS_DIR, "test.conf")
|
34
|
+
REDIS_PID = File.join(REDIS_DIR, "db", "redis.pid")
|
35
|
+
|
36
|
+
task :default => :run
|
37
|
+
|
38
|
+
desc "Run tests and manage server start/stop"
|
39
|
+
task :run => [:start, :test, :stop]
|
40
|
+
|
41
|
+
desc "Start the Redis server"
|
42
|
+
task :start do
|
43
|
+
redis_running = \
|
44
|
+
begin
|
45
|
+
File.exists?(REDIS_PID) && Process.kill(0, File.read(REDIS_PID).to_i)
|
46
|
+
rescue Errno::ESRCH
|
47
|
+
FileUtils.rm REDIS_PID
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
system "redis-server #{REDIS_CNF}" unless redis_running
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Stop the Redis server"
|
55
|
+
task :stop do
|
56
|
+
if File.exists?(REDIS_PID)
|
57
|
+
Process.kill "INT", File.read(REDIS_PID).to_i
|
58
|
+
FileUtils.rm REDIS_PID
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "Run the test suite"
|
63
|
+
task :test do
|
64
|
+
require 'cutest'
|
65
|
+
|
66
|
+
Cutest.run(Dir['./test/**/*_test.rb'])
|
67
|
+
end
|
68
|
+
|
69
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
70
|
+
pkg.gem_spec = spec
|
71
|
+
end
|
72
|
+
|
73
|
+
desc "install the gem locally"
|
74
|
+
task :install => [:package] do
|
75
|
+
sh %{gem install pkg/#{GEM}-#{GEM_VERSION}}
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "create a gemspec file"
|
79
|
+
task :gemspec do
|
80
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
81
|
+
file.puts spec.to_ruby
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
desc "Generate YARDoc"
|
86
|
+
task :yardoc do
|
87
|
+
require "yard"
|
88
|
+
|
89
|
+
opts = ["--title", "A Ruby client for Redis"]
|
90
|
+
|
91
|
+
YARD::CLI::Yardoc.run(*opts)
|
92
|
+
end
|
93
|
+
|
94
|
+
namespace :commands do
|
95
|
+
def redis_commands
|
96
|
+
$redis_commands ||= begin
|
97
|
+
require "open-uri"
|
98
|
+
open("http://dimaion.com/redis/master").read.split
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
task :doc do
|
103
|
+
source = File.read("lib/redis.rb")
|
104
|
+
|
105
|
+
redis_commands.each do |name, text|
|
106
|
+
source.sub!(/(?:^ *#.*\n)*^( *)def #{name}(\(|$)/) do
|
107
|
+
indent, extra_args = $1, $2
|
108
|
+
comment = "#{indent}# #{text.strip}"
|
109
|
+
|
110
|
+
IO.popen("par p#{2 + indent.size} 80", "r+") do |io|
|
111
|
+
io.puts comment
|
112
|
+
io.close_write
|
113
|
+
comment = io.read
|
114
|
+
end
|
115
|
+
|
116
|
+
"#{comment}#{indent}def #{name}#{extra_args}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
File.open("lib/redis.rb", "w") { |f| f.write(source) }
|
121
|
+
end
|
122
|
+
|
123
|
+
task :verify do
|
124
|
+
require "redis"
|
125
|
+
require "stringio"
|
126
|
+
|
127
|
+
log = StringIO.new
|
128
|
+
|
129
|
+
at_exit do
|
130
|
+
redis = Redis.new
|
131
|
+
|
132
|
+
report = ["Command", "\033[0mDefined?\033[0m", "\033[0mTested?\033[0m"]
|
133
|
+
|
134
|
+
yes, no = "\033[1;32mYes\033[0m", "\033[1;31mNo\033[0m"
|
135
|
+
|
136
|
+
redis_commands.sort.each do |name, _|
|
137
|
+
defined, tested = redis.respond_to?(name), log.string[">> #{name.upcase}"]
|
138
|
+
|
139
|
+
next if defined && tested
|
140
|
+
|
141
|
+
report << name
|
142
|
+
report << (defined ? yes : no)
|
143
|
+
report << (tested ? yes : no)
|
144
|
+
end
|
145
|
+
|
146
|
+
IO.popen("rs 0 3", "w") do |io|
|
147
|
+
io.puts report.join("\n")
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
Dir["test/**/redis_test.rb"].each { |f| require "./#{f}" }
|
152
|
+
|
153
|
+
RedisTest::OPTIONS[:logger] = Logger.new(log)
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Run with
|
2
|
+
#
|
3
|
+
# $ ruby -Ilib benchmarking/logging.rb
|
4
|
+
#
|
5
|
+
|
6
|
+
begin
|
7
|
+
require "bench"
|
8
|
+
rescue LoadError
|
9
|
+
$stderr.puts "`gem install bench` and try again."
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
require "redis"
|
14
|
+
require "logger"
|
15
|
+
|
16
|
+
def log(level, namespace = nil)
|
17
|
+
logger = (namespace || Kernel).const_get(:Logger).new("/dev/null")
|
18
|
+
logger.level = (namespace || Logger).const_get(level)
|
19
|
+
logger
|
20
|
+
end
|
21
|
+
|
22
|
+
def stress(redis)
|
23
|
+
redis.flushdb
|
24
|
+
|
25
|
+
n = (ARGV.shift || 2000).to_i
|
26
|
+
|
27
|
+
n.times do |i|
|
28
|
+
key = "foo:#{i}"
|
29
|
+
redis.set key, i
|
30
|
+
redis.get key
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
default = Redis.new
|
35
|
+
|
36
|
+
logging_redises = [
|
37
|
+
Redis.new(:logger => log(:DEBUG)),
|
38
|
+
Redis.new(:logger => log(:INFO)),
|
39
|
+
]
|
40
|
+
|
41
|
+
begin
|
42
|
+
require "log4r"
|
43
|
+
|
44
|
+
logging_redises += [
|
45
|
+
Redis.new(:logger => log(:DEBUG, Log4r)),
|
46
|
+
Redis.new(:logger => log(:INFO, Log4r)),
|
47
|
+
]
|
48
|
+
rescue LoadError
|
49
|
+
$stderr.puts "Log4r not installed. `gem install log4r` if you want to compare it against Ruby's Logger (spoiler: it's much faster)."
|
50
|
+
end
|
51
|
+
|
52
|
+
benchmark "Default options (no logger)" do
|
53
|
+
stress(default)
|
54
|
+
end
|
55
|
+
|
56
|
+
logging_redises.each do |redis|
|
57
|
+
benchmark "#{redis.client.logger.class} on #{Logger::SEV_LABEL[redis.client.logger.level]}" do
|
58
|
+
stress(redis)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
run 10
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "benchmark"
|
2
|
+
|
3
|
+
$:.push File.join(File.dirname(__FILE__), 'lib')
|
4
|
+
|
5
|
+
require 'redis'
|
6
|
+
|
7
|
+
ITERATIONS = 10000
|
8
|
+
|
9
|
+
@r = Redis.new
|
10
|
+
|
11
|
+
Benchmark.bmbm do |benchmark|
|
12
|
+
benchmark.report("set") do
|
13
|
+
@r.flushdb
|
14
|
+
|
15
|
+
ITERATIONS.times do |i|
|
16
|
+
@r.set("foo#{i}", "Hello world!")
|
17
|
+
@r.get("foo#{i}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
benchmark.report("set (pipelined)") do
|
22
|
+
@r.flushdb
|
23
|
+
|
24
|
+
@r.pipelined do
|
25
|
+
ITERATIONS.times do |i|
|
26
|
+
@r.set("foo#{i}", "Hello world!")
|
27
|
+
@r.get("foo#{i}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
benchmark.report("lpush+ltrim") do
|
33
|
+
@r.flushdb
|
34
|
+
|
35
|
+
ITERATIONS.times do |i|
|
36
|
+
@r.lpush "lpush#{i}", i
|
37
|
+
@r.ltrim "ltrim#{i}", 0, 30
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
benchmark.report("lpush+ltrim (pipelined)") do
|
42
|
+
@r.flushdb
|
43
|
+
|
44
|
+
@r.pipelined do
|
45
|
+
ITERATIONS.times do |i|
|
46
|
+
@r.lpush "lpush#{i}", i
|
47
|
+
@r.ltrim "ltrim#{i}", 0, 30
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|