nofxx-tokyo_store 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -21,12 +21,12 @@ Rails (enviroment.rb)
21
21
  config.gem 'nofxx-tokyo_store', :lib => 'tokyo_store'
22
22
  ActionController::Base.session_store = Rack::Session::Tokyo
23
23
 
24
+ Start Tyrant
24
25
 
25
- == Run
26
+ ttserver data.tch
26
27
 
27
- Just start tyrant
28
28
 
29
- ttserver data.tch
29
+ Have fun!
30
30
 
31
31
 
32
32
  == Thanks
data/Rakefile CHANGED
@@ -16,12 +16,29 @@ rescue LoadError
16
16
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
17
  end
18
18
 
19
- require 'rake/testtask'
20
- Rake::TestTask.new(:spec) do |spec|
19
+ require 'spec/rake/spectask'
20
+ Spec::Rake::SpecTask.new(:spec) do |spec|
21
21
  spec.libs << 'lib' << 'spec'
22
- spec.pattern = 'spec/**/*_spec.rb'
23
- spec.verbose = true
22
+ spec.spec_files = FileList['spec/**/*_spec.rb']
24
23
  end
25
24
 
25
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
26
+ spec.libs << 'lib' << 'spec'
27
+ spec.pattern = 'spec/**/*_spec.rb'
28
+ spec.rcov = true
29
+ end
26
30
  task :default => :spec
27
31
 
32
+ require 'rake/rdoctask'
33
+ Rake::RDocTask.new do |rdoc|
34
+ if File.exist?('VERSION')
35
+ version = File.read('VERSION').chomp
36
+ else
37
+ version = ""
38
+ end
39
+
40
+ rdoc.rdoc_dir = 'rdoc'
41
+ rdoc.title = "foo #{version}"
42
+ rdoc.rdoc_files.include('README*')
43
+ rdoc.rdoc_files.include('lib/**/*.rb')
44
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.8
1
+ 0.1.9
data/benchmark/cache.rb CHANGED
@@ -3,118 +3,132 @@
3
3
  #
4
4
  # Benchmark vs MemCacheStore on memcached and tyrant
5
5
  #
6
+ $: << File.join(File.dirname(__FILE__), "/../lib")
6
7
  require 'rubygems'
7
8
  require 'active_support'
8
- $LOAD_PATH.unshift(File.dirname(__FILE__))
9
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
10
9
  require 'cache/tokyo_store'
11
- #include TokyoCabinet
10
+ require 'redis-store'
11
+ require 'cache/rails/redis_store'
12
12
 
13
13
  P = "x" * 100
14
14
  M = P * 10
15
15
  G = M * 10
16
- X = { :small => P, :medium => M, :big => G}
16
+ A = [P, M, G]
17
+ X = { :small => P, :medium => M, :big => G }
18
+ class User; attr_accessor :name, :info; end
19
+ u = User.new; u.name = P; u.info = G
20
+ O = u
21
+ T = ARGV[0].to_i || 10000
17
22
 
18
23
  #TODO: Cabinet & memcached C bindings
19
- @tokyo = ActiveSupport::Cache.lookup_store :tokyo_store, "localhost:1978"
20
- @memca = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost:11211"
21
- @memto = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost:1978"
24
+ TEST = {
25
+ "TokyoStore" => ActiveSupport::Cache.lookup_store(:tokyo_store, "localhost:1978"),
26
+ "MemTokyo" => ActiveSupport::Cache.lookup_store(:mem_cache_store, "localhost:1978"),
27
+ "RedisStore" => ActiveSupport::Cache.lookup_store(:redis_store, "localhost:6379"),
28
+ "MemCache" => ActiveSupport::Cache.lookup_store(:mem_cache_store, "localhost:11211"),
29
+ }
22
30
 
23
31
  puts " Write"
24
- puts "--------------"
32
+ puts "----------"
25
33
  Benchmark.bmbm do |b|
26
- b.report("TokyoStore# P") { 10_000.times { |i| @tokyo.write i.to_s, P }}
27
- b.report("MemCacheD # P") { 10_000.times { |i| @memca.write i.to_s, P }}
28
- b.report("MemCacheT # P") { 10_000.times { |i| @memto.write i.to_s, P }}
29
- b.report("TokyoStore# M") { 10_000.times { |i| @tokyo.write i.to_s, M }}
30
- b.report("MemCacheD # M") { 10_000.times { |i| @memca.write i.to_s, M }}
31
- b.report("MemCacheT # M") { 10_000.times { |i| @memto.write i.to_s, M }}
32
- b.report("TokyoStore# G") { 10_000.times { |i| @tokyo.write i.to_s, G }}
33
- b.report("MemCacheD # G") { 10_000.times { |i| @memca.write i.to_s, G }}
34
- b.report("MemCacheT # G") { 10_000.times { |i| @memto.write i.to_s, G }}
35
- b.report("TokyoStore# D") { 10_000.times { |i| @tokyo.delete i.to_s }}
36
- b.report("MemCacheD # D") { 10_000.times { |i| @memca.delete i.to_s }}
37
- b.report("MemCacheT # D") { 10_000.times { |i| @memto.delete i.to_s }}
38
- b.report("TokyoStore# +") { 10_000.times { |i| @tokyo.increment i.to_s }}
39
- b.report("MemCacheD # +") { 10_000.times { |i| @memca.increment i.to_s }}
40
- b.report("MemCacheT # +") { 10_000.times { |i| @memto.increment i.to_s }}
41
- b.report("TokyoStore# -") { 10_000.times { |i| @tokyo.decrement i.to_s }}
42
- b.report("MemCacheD # -") { 10_000.times { |i| @memca.decrement i.to_s }}
43
- b.report("MemCacheT # -") { 10_000.times { |i| @memto.decrement i.to_s }}
34
+ TEST.each_pair do |k,s|
35
+ b.report("#{k} P") { T.times { |i| s.write i.to_s, P }}
36
+ b.report("#{k} M") { T.times { |i| s.write i.to_s, M }}
37
+ b.report("#{k} G") { T.times { |i| s.write i.to_s, G }}
38
+ b.report("#{k} Obj") { T.times { |i| s.write i.to_s, O }}
39
+ b.report("#{k} Hash") { T.times { |i| s.write i.to_s, X }}
40
+ b.report("#{k} Array") { T.times { |i| s.write i.to_s, A }}
41
+ b.report("#{k} Delete") { T.times { |i| s.delete i.to_s }}
42
+ b.report("#{k} +") { T.times { |i| s.increment i.to_s }}
43
+ b.report("#{k} -") { T.times { |i| s.decrement i.to_s }}
44
+ end
44
45
  end
45
46
 
46
47
  puts " Read"
47
- puts "--------------"
48
- #TODO: implement read with diff data. ALl should probably be 0 here
48
+ puts "----------"
49
+ TEST.each { |p| 10_000.times { |i| p[1].write i.to_s, G }}
50
+ #TODO: implement read with diff data.
49
51
  Benchmark.bmbm do |b|
50
- b.report("TokyoStore# Seq") { 10_000.times { |i| @tokyo.read i.to_s }}
51
- b.report("MemCacheD # Seq") { 10_000.times { |i| @memca.read i.to_s }}
52
- b.report("MemCacheT # Seq") { 10_000.times { |i| @memto.read i.to_s }}
53
- b.report("TokyoStore# Rand") { 10_000.times { |i| @tokyo.read rand(i).to_s }}
54
- b.report("MemCacheD # Rand") { 10_000.times { |i| @memca.read rand(i).to_s }}
55
- b.report("MemCacheT # Rand") { 10_000.times { |i| @memto.read rand(i).to_s }}
56
- b.report("TokyoStore# Exist") { 10_000.times { |i| @tokyo.exist? i.to_s }}
57
- b.report("MemCacheD # Exist") { 10_000.times { |i| @memca.exist? i.to_s }}
58
- b.report("MemCacheT # Exist") { 10_000.times { |i| @memto.exist? i.to_s }}
52
+ TEST.each_pair do |k,s|
53
+ k = s.class.to_s.split("::")[-1]
54
+ b.report("#{k} Seq") { T.times { |i| s.read rand(i).to_s }}
55
+ b.report("#{k} Rand") { T.times { |i| s.read rand(i).to_s }}
56
+ b.report("#{k} Exist") { T.times { |i| s.exist? i.to_s }}
57
+ end
59
58
  end
60
59
 
61
60
  puts
62
61
  thr = []
63
62
  Benchmark.bmbm do |b|
64
- b.report("Tokyo # W") { 100.times { |j| thr << Thread.new { 100.times { |i| @tokyo.write "#{j}-#{i}", X }}}; thr.each { |t| t.join }; thr = [] }
65
- b.report("MemCa # W") { 100.times { |j| thr << Thread.new { 100.times { |i| @memca.write "#{j}-#{i}", X}}}; thr.each { |t| t.join }; thr = [] }
66
- b.report("MemTo # W") { 100.times { |j| thr << Thread.new { 100.times { |i| @memto.write "#{j}-#{i}", X}}}; thr.each { |t| t.join }; thr = [] }
67
- b.report("Tokyo # R") { 100.times { |j| thr << Thread.new { 100.times { |i| @tokyo.read "#{j}-#{i}" }}}; thr.each { |t| t.join }; thr = [] }
68
- b.report("MemCa # R") { 100.times { |j| thr << Thread.new { 100.times { |i| @memca.read "#{j}-#{i}"}}}; thr.each { |t| t.join }; thr = [] }
69
- b.report("MemTo # R") { 100.times { |j| thr << Thread.new { 100.times { |i| @memto.read "#{j}-#{i}"}}}; thr.each { |t| t.join }; thr = [] }
63
+ TEST.each_pair do |k,s|
64
+ b.report("#{k} TW") { (T/2).times { |j| thr << Thread.new { (T/2).times { |i| s.write "#{j}-#{i}", X }}}; thr.each { |t| t.join }; thr = [] }
65
+ b.report("#{k} TR") { (T/2).times { |j| thr << Thread.new { (T/2).times { |i| s.read "#{j}-#{i}" }}}; thr.each { |t| t.join }; thr = [] }
66
+ end
70
67
  end
71
68
 
72
69
  __END__
73
70
 
74
-
71
+ *NOTE: Redis and Memcache support native expiration, Tokyo doesn't.
72
+ Wondering the impact of this feature written in ruby...
75
73
 
76
74
  Core 2 Duo 8500 - 3.16Ghz
77
75
  ------------------------------------------------------------
78
76
  Write
79
77
  -------------
80
78
  TokyoStore# P 0.140000 0.090000 0.230000 ( 0.367587)
79
+ RedisStore# P 0.340000 0.090000 0.430000 ( 0.542441)
81
80
  MemCacheD # P 0.570000 0.160000 0.730000 ( 0.829167)
82
81
  MemCacheT # P 0.560000 0.170000 0.730000 ( 0.897084)
82
+
83
83
  TokyoStore# M 0.170000 0.100000 0.270000 ( 0.448071)
84
+ RedisStore# M 0.360000 0.120000 0.480000 ( 0.641083)
84
85
  MemCacheD # M 0.610000 0.140000 0.750000 ( 0.878559)
85
86
  MemCacheT # M 0.630000 0.140000 0.770000 ( 0.951748)
87
+
86
88
  TokyoStore# G 0.410000 0.090000 0.500000 ( 0.976746)
89
+ RedisStore# G 0.930000 0.170000 1.100000 ( 1.572024)
87
90
  MemCacheD # G 1.000000 0.200000 1.200000 ( 1.429635)
88
91
  MemCacheT # G 1.060000 0.170000 1.230000 ( 1.558731)
89
- TokyoStore# X 0.480000 0.130000 0.610000 ( 1.299556)
90
- MemCacheD # X 1.460000 0.280000 1.740000 ( 1.980678)
91
- MemCacheT # X 1.230000 0.230000 1.460000 ( 1.856561)
92
+
92
93
  TokyoStore# D 0.220000 0.170000 0.390000 ( 0.707877)
94
+ RedisStore# D 0.240000 0.110000 0.350000 ( 0.474265)
93
95
  MemCacheD # D 0.560000 0.110000 0.670000 ( 0.775865)
94
96
  MemCacheT # D 0.560000 0.140000 0.700000 ( 0.860964)
97
+
95
98
  TokyoStore# + 0.230000 0.190000 0.420000 ( 0.654690)
99
+ RedisStore# + 0.200000 0.120000 0.320000 ( 0.494333)
96
100
  MemCacheD # + 0.570000 0.130000 0.700000 ( 0.801407)
97
101
  MemCacheT # + 0.540000 0.190000 0.730000 ( 0.937882)
102
+
98
103
  TokyoStore# - 0.200000 0.210000 0.410000 ( 0.669899)
104
+ RedisStore# - 0.240000 0.120000 0.360000 ( 0.511279)
99
105
  MemCacheD # - 0.600000 0.100000 0.700000 ( 0.778212)
100
106
  MemCacheT # - 0.600000 0.140000 0.740000 ( 0.983345)
101
107
 
102
108
  Read
103
109
  --------------
104
110
  TokyoStore# Seq 0.440000 0.150000 0.590000 ( 0.858501)
111
+ RedisStore# Seq 0.660000 0.130000 0.790000 ( 1.039310)
105
112
  MemCacheD # Seq 0.830000 0.220000 1.050000 ( 1.135630)
106
113
  MemCacheT # Seq 1.210000 0.190000 1.400000 ( 1.754004)
114
+
107
115
  TokyoStore# Rand 0.490000 0.200000 0.690000 ( 1.003466)
116
+ RedisStore# Rand 0.580000 0.210000 0.790000 ( 1.877162)
108
117
  MemCacheD # Rand 0.870000 0.170000 1.040000 ( 1.135382)
109
118
  MemCacheT # Rand 1.410000 0.230000 1.640000 ( 1.971372)
119
+
110
120
  TokyoStore# Exist 0.460000 0.140000 0.600000 ( 0.845920)
121
+ RedisStore# Exist 0.550000 0.250000 0.800000 ( 1.658580)
111
122
  MemCacheD # Exist 0.810000 0.220000 1.030000 ( 1.138310)
112
123
  MemCacheT # Exist 1.150000 0.250000 1.400000 ( 1.760770)
113
124
 
114
125
 
115
126
  Tokyo # W 0.510000 0.150000 0.660000 ( 1.023739)
127
+ Redis # W 0.540000 0.140000 0.680000 ( 1.032881)
116
128
  MemCa # W 2.530000 0.210000 2.740000 ( 3.072881)
117
129
  MemTo # W 2.600000 0.280000 2.880000 ( 3.344125)
130
+
118
131
  Tokyo # R 0.680000 0.210000 0.890000 ( 2.547828)
132
+ Redis # R 0.710000 0.220000 0.930000 ( 2.599269)
119
133
  MemCa # R 2.190000 0.240000 2.430000 ( 2.977408)
120
134
  MemTo # R 3.210000 0.330000 3.540000 ( 4.298882)
@@ -0,0 +1,75 @@
1
+ #
2
+ # Tokyo Store
3
+ #
4
+ # Session Benchmark vs Redis Store
5
+ #
6
+ # TODO: memcache
7
+ #
8
+ $: << File.join(File.dirname(__FILE__), "/../lib")
9
+ require 'rubygems'
10
+ require 'benchmark'
11
+ require 'rack'
12
+ require 'tokyo_store'
13
+ require 'redis-store'
14
+ #S = [Rack::Session::Tokyo::DEFAULT_OPTIONS[:key], { :test => "foo"}]
15
+ T = ARGV[0].to_i || 10000
16
+
17
+ rack = lambda do |env|
18
+ env["rack.session"]["counter"] ||= 0
19
+ env["rack.session"]["counter"] += 1
20
+ Rack::Response.new(env["rack.session"].inspect).to_a
21
+ end
22
+
23
+ TEST = {
24
+ "Tokyo" => Rack::Session::Tokyo.new(rack),
25
+ "Redis" => Rack::Session::Redis.new(rack),
26
+ }
27
+ bar = "_" * 45
28
+
29
+ puts "\n#{bar} GET"
30
+ Benchmark.bmbm do |b|
31
+ TEST.each_pair do |n,s|
32
+ b.report(n) do T.times do
33
+ req = Rack::MockRequest.new(s)
34
+ cookie = req.get("/")["Set-Cookie"]
35
+ req.get("/", "HTTP_COOKIE" => cookie)
36
+ end end
37
+ end
38
+ end
39
+
40
+ puts "\n#{bar} SET"
41
+ Benchmark.bmbm do |b|
42
+ TEST.each_pair do |n,s|
43
+ b.report(n) { T.times { Rack::MockRequest.new(s).get("/") }}
44
+ end
45
+ end
46
+
47
+ puts "\n#{bar} EXIST"
48
+ Benchmark.bmbm do |b|
49
+ TEST.each_pair do |n,s|
50
+ b.report(n) do T.times do
51
+ Rack::MockRequest.new(s).get("/", "HTTP_COOKIE" => "rack.session=badbadcookie")
52
+ end end
53
+ end
54
+ end
55
+
56
+
57
+ __END__
58
+
59
+ *Note: Tokyo uses FFI adapter, while redis a pure ruby.
60
+ Both comparable to memcache pr too. Check the cache benchmark.
61
+
62
+ _____________________________________________ GET
63
+ Tokyo 6.310000 1.030000 7.340000 ( 8.511138)
64
+ Redis 7.300000 1.010000 8.310000 ( 9.325441)
65
+ ------------------------------- total: 15.650000sec
66
+
67
+ _____________________________________________ SET
68
+ Tokyo 3.340000 0.540000 3.880000 ( 4.562920)
69
+ Redis 3.960000 0.540000 4.500000 ( 5.030627)
70
+ -------------------------------- total: 8.380000sec
71
+
72
+ _____________________________________________ EXIST
73
+ Tokyo 4.090000 0.650000 4.740000 ( 5.537898)
74
+ Redis 4.700000 0.700000 5.400000 ( 6.061131)
75
+ ------------------------------- total: 10.140000sec
@@ -6,6 +6,7 @@ module ActiveSupport
6
6
  # A cache store implementation which stores data in Tokyo Cabinet
7
7
  #
8
8
  # Special features:
9
+ # - Substring match
9
10
  # - Clustering and load balancing. TODO
10
11
  # - Time-based expiry support. TODO (Lua)
11
12
  # - Per-request in memory cache for all communication with the Tokyo server(s).
@@ -109,7 +110,8 @@ module ActiveSupport
109
110
  end
110
111
 
111
112
  def delete_matched(matcher, options = nil) # :nodoc:
112
- #TODO @data.ldelete?
113
+ super
114
+ @data.delete_keys_with_prefix(matcher)
113
115
  end
114
116
 
115
117
  def clear
@@ -15,13 +15,6 @@ module Rack
15
15
  end
16
16
  end
17
17
 
18
- def generate_sid
19
- loop do
20
- sid = super
21
- break sid unless @pool[sid]
22
- end
23
- end
24
-
25
18
  private
26
19
  def get_session(env, sid)
27
20
  @mutex.lock if env['rack.multithread']
@@ -43,7 +36,7 @@ module Rack
43
36
 
44
37
  def set_session(env, sid, new_session, options)
45
38
  @mutex.lock if env['rack.multithread']
46
- session = Marshal.load(session) if session = @pool[sid]
39
+ session = Marshal.load(session) rescue session if session = @pool[sid]
47
40
  if options[:renew] || options[:drop]
48
41
  @pool.delete sid
49
42
  return false if options[:drop]
@@ -55,9 +48,13 @@ module Rack
55
48
  @pool[sid] = options && options[:raw] ? session : Marshal.dump(session)
56
49
  return sid
57
50
  rescue => e
51
+ if e =~ /refused/
58
52
  warn "#{self} is unable to find server, error: #{e}"
59
53
  warn $!.inspect
60
54
  return false
55
+ else
56
+ raise e
57
+ end
61
58
  ensure
62
59
  @mutex.unlock if env['rack.multithread']
63
60
  end
@@ -79,6 +76,13 @@ module Rack
79
76
  cur
80
77
  end
81
78
 
79
+ def generate_sid
80
+ loop do
81
+ sid = super
82
+ break sid unless @pool[sid]
83
+ end
84
+ end
85
+
82
86
  end
83
87
 
84
88
  end
@@ -141,10 +141,13 @@ describe "TokyoStore" do
141
141
  end
142
142
 
143
143
  it "should delete matched" do
144
- @cache.write("val", 1)
145
- @cache.write("value", 1)
146
- @cache.write("not", 1)
144
+ ["val", "value", "vall", "val/1", "vla", "xla", "xla/1"].each do |v|
145
+ @cache.write(v, 1)
146
+ end
147
+
147
148
  @cache.delete_matched('val')
149
+ ["val", "value", "vall", "val/1"].each { |v| @cache.read(v).should be_nil }
150
+ ["vla", "xla", "xla/1"].each { |v| @cache.read(v).should eql(1) }
148
151
  end
149
152
 
150
153
  end
data/tokyo_store.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{tokyo_store}
5
- s.version = "0.1.8"
5
+ s.version = "0.1.9"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Marcos Piccinini"]
9
- s.date = %q{2009-07-04}
9
+ s.date = %q{2009-07-05}
10
10
  s.email = %q{x@nofxx.com}
11
11
  s.extra_rdoc_files = [
12
12
  "LICENSE",
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
  "Rakefile",
21
21
  "VERSION",
22
22
  "benchmark/cache.rb",
23
+ "benchmark/session.rb",
23
24
  "lib/cache/tokyo_store.rb",
24
25
  "lib/rack/cache/tokyo_entitystore.rb",
25
26
  "lib/rack/cache/tokyo_metastore.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nofxx-tokyo_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcos Piccinini
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-04 00:00:00 -07:00
12
+ date: 2009-07-05 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -30,6 +30,7 @@ files:
30
30
  - Rakefile
31
31
  - VERSION
32
32
  - benchmark/cache.rb
33
+ - benchmark/session.rb
33
34
  - lib/cache/tokyo_store.rb
34
35
  - lib/rack/cache/tokyo_entitystore.rb
35
36
  - lib/rack/cache/tokyo_metastore.rb