cachedis 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cachedis (0.0.1)
4
+ cachedis (0.0.2)
5
5
  redis
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -8,24 +8,13 @@ Cachedis caches your expensive queries to a Redis instance so the next time you
8
8
 
9
9
  ## Documentation
10
10
 
11
- You can specify two types of options via constants:
12
-
13
- * `CACHEDIS_DEFAULT_OPTIONS`
14
- - Passed directly to [redis-rb][rr]
15
- - Options like host options, port options, etc.
16
- * `CACHEDIS_DEFAULT_QUERY_OPTIONS`
17
- - Default options for the `cachedis` queries
18
- - For instance if you always want queries to expire in an hour:
19
- - `CACHEDIS_DEFAULT_QUERY_OPTIONS = { :expire => 60 * 60 * 60}`
20
- - Overridden by options passed to `cachedis` directly
21
-
22
11
  `cachedis` takes two arguments in addition to a block which should return whatever you want `cachedis` to cache:
23
12
 
24
13
  key, options = {}
25
14
 
26
15
  The key is the name of the key under which the objects are saved as in Redis. Options are send directly to the Redis instance in along. For instance the option could be expiring the key at a certain time:
27
16
 
28
- include CachedisInterface
17
+ include Cachedis::Interface
29
18
 
30
19
  # expire in an hour using Redis' EXPIRE command
31
20
  cachedis 'users:all:with_avatars', :expire => 60 * 60 * 60 do
@@ -37,6 +26,15 @@ The key is the name of the key under which the objects are saved as in Redis. Op
37
26
  # insert expensive query here
38
27
  end
39
28
 
29
+ ### Configuration
30
+
31
+ If you want to configure the server(s) or port(s) for `cachedis` to use, you should override the default `Cachedis::Interface#cachedis` method. Whatever you pass to `#new` is passed directly to the instance of the Redis object from the [redis-rb][rr] library:
32
+
33
+ def cachedis(name, options = {}, &block)
34
+ @cachedis ||= Cachedis.new(:host => "10.0.1.1", :port => 6380)
35
+ @cachedis.cachedis(name, options, &block)
36
+ end
37
+
40
38
  ## Installation and dependencies
41
39
 
42
40
  Dependencies: [redis-rb][rr]
@@ -45,12 +43,25 @@ Install: `gem install cachedis`
45
43
 
46
44
  [Redis](http://redis.io) should be running in the background, start it with `redis-server`.
47
45
 
46
+ ## Serialization
47
+
48
+ I experimented and benchmarked with `JSON`, `YAML` and `Marshal` using the drivers in the Ruby standard libary with [this script](https://gist.github.com/858604).
49
+
50
+ Marshal is about 2x as fast as the other formats. However, it's also the one that is gonna take up the most space, but it's so little that it should not matter.
51
+
52
+ You can switch serialization driver if you need to by overriding `Cachedis.serializer`. The serializer must respond to `#load` and `#dump`, remember to require it before using it with `cachedis`:
53
+
54
+ module Cachedis
55
+ def self.serializer
56
+ "YAML"
57
+ end
58
+ end
59
+
48
60
  ## Wishlist/To do/To consider
49
61
 
50
62
  * ActiveRecord integration
51
63
  - `Post.all.expensive_operation.cachedis`
52
64
  * Make expirement time optional
53
- * Best serializing?
54
65
  * Sexify the API
55
66
  - Make it easier to specialize expirement time (e.g. `:expire => 4.hours`), or just let this be for ActiveSupport users only?
56
67
  * Rename `Cachedis#cachedis`?
@@ -0,0 +1,75 @@
1
+ require 'benchmark'
2
+ require 'redis'
3
+ require 'yaml'
4
+ require 'json'
5
+
6
+ N = 10000
7
+
8
+ Benchmark.bm do |r|
9
+ @redis = Redis.new
10
+ @serialize_me = { :lol => 'test', "ohai" => 'llllll', :array => [12,321,231,23, { :hi => 'hej'}]}
11
+
12
+ r.report("YAML Save") do
13
+ puts 'Yaml'
14
+ puts YAML.dump(@serialize_me).length
15
+
16
+ N.times do |n|
17
+ @redis.set "yaml-#{n}", YAML.dump(@serialize_me)
18
+ end
19
+ end
20
+
21
+ r.report("YAML Load") do
22
+ N.times do |n|
23
+ YAML.load(@redis.get "yaml-#{n}")
24
+ end
25
+ end
26
+
27
+ r.report("Marshal Save") do
28
+ puts 'Marshal'
29
+ puts Marshal.dump(@serialize_me).length
30
+
31
+ N.times do |n|
32
+ @redis.set "marshal-#{n}", Marshal.dump(@serialize_me)
33
+ end
34
+ end
35
+
36
+ r.report("Marshal Load") do
37
+ N.times do |n|
38
+ Marshal.load(@redis.get "marshal-#{n}")
39
+ end
40
+ end
41
+
42
+ r.report("JSON Save") do
43
+ puts 'JSON'
44
+ puts JSON.dump(@serialize_me).length
45
+
46
+ N.times do |n|
47
+ @redis.set "json-#{n}", JSON.dump(@serialize_me)
48
+ end
49
+ end
50
+
51
+ r.report("JSON Load") do
52
+ N.times do |n|
53
+ JSON.load(@redis.get "json-#{n}")
54
+ end
55
+ end
56
+ end
57
+
58
+ # N = 10000
59
+ # user system total real
60
+ # YAML Save 1.170000 0.160000 1.330000 ( 1.444772)
61
+ # YAML Load 0.560000 0.130000 0.690000 ( 0.781064)
62
+ # Marshal Save 0.290000 0.140000 0.430000 ( 0.527284)
63
+ # Marshal Load 0.260000 0.160000 0.420000 ( 0.507964)
64
+ # JSON Save 0.670000 0.170000 0.840000 ( 0.970764)
65
+ # JSON Load 0.310000 0.190000 0.500000 ( 0.568105
66
+ #
67
+ # N = 100000
68
+ # user system total real
69
+ # YAML Save 1.170000 0.160000 1.330000 ( 1.444772)
70
+ # YAML Load 0.560000 0.130000 0.690000 ( 0.781064)
71
+ # Marshal Save 0.290000 0.140000 0.430000 ( 0.527284)
72
+ # Marshal Load 0.260000 0.160000 0.420000 ( 0.507964)
73
+ # JSON Save 0.670000 0.170000 0.840000 ( 0.970764)
74
+ # JSON Load 0.310000 0.190000 0.500000 ( 0.568105
75
+
@@ -1,43 +1,45 @@
1
1
  require 'redis'
2
- require 'yaml'
3
2
 
4
- class Cachedis
5
- attr_reader :redis_instance
6
-
7
- def initialize(options = {})
8
- redis(options)
3
+ module Cachedis
4
+ def self.serializer
5
+ "Marshal"
9
6
  end
10
7
 
11
- def cachedis(key, options = {}, &block)
12
- result = yield
13
-
14
- return redis.get key if redis.exists key
8
+ class Cacher
9
+ def initialize(options = {})
10
+ redis(options)
11
+ end
15
12
 
16
- result = result.to_yaml
17
- redis.set key, result
18
- pass_options_to_redis(options)
13
+ def cachedis(key, options = {}, &block)
14
+ result = yield
15
+
16
+ serializer = Kernel.const_get(Cachedis.serializer)
17
+ return serializer.load(redis.get(key)) if redis.exists key
19
18
 
20
- result
21
- end
19
+ result = serializer.dump(result)
20
+ redis.set key, result
21
+ pass_options_to_redis(options)
22
22
 
23
- def redis(options = {})
24
- @redis_instance ||= Redis.new(options)
25
- end
23
+ result
24
+ end
26
25
 
27
- private
28
- def pass_options_to_redis(options)
29
- options.each do |option, argument|
30
- arguments = *[argument] if argument.is_a?(Array)
31
- redis.send(option, arguments || argument)
26
+ def redis(options = {})
27
+ @redis_instance ||= Redis.new(options)
28
+ end
29
+
30
+ private
31
+ def pass_options_to_redis(options)
32
+ options.each do |option, argument|
33
+ arguments = *[argument] if argument.is_a?(Array)
34
+ redis.send(option, arguments || argument)
35
+ end
32
36
  end
33
37
  end
34
- end
35
38
 
36
- module CachedisInterface
37
- def self.cachedis(name, options = {}, &block)
38
- cachedis = Cachedis.new((CACHEDIS_DEFAULT_OPTIONS if defined?(CACHEDIS_DEFAULT_OPTIONS))|| {})
39
-
40
- query_options = ((CACHEDIS_DEFAULT_QUERY_OPTIONS if defined?(CACHEDIS_OPTIONS)) || {}).merge(options)
41
- cachedis.cachedis(name, query_options, &block)
39
+ module Interface
40
+ def self.cachedis(name, options = {}, &block)
41
+ cachedis = Cacher.new
42
+ cachedis.cachedis(name, options, &block)
43
+ end
42
44
  end
43
45
  end
@@ -1,3 +1,3 @@
1
- class Cachedis
2
- VERSION = "0.0.2"
1
+ module Cachedis
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Cachedis do
3
+ describe Cachedis::Cacher do
4
4
  include HelperMethods
5
5
 
6
6
  before do
7
- @cachedis = Cachedis.new
7
+ @cachedis = Cachedis::Cacher.new
8
8
  end
9
9
 
10
10
  describe 'when setting something' do
@@ -20,14 +20,12 @@ describe Cachedis do
20
20
 
21
21
  describe 'when setting and later retrieving something' do
22
22
  it 'retrieves from redis cache' do
23
- with_cache('query')
24
- @cachedis.redis_instance.should_not_receive(:set)
23
+ with_cache(Marshal.dump('query'))
24
+ @cachedis.redis.should_not_receive(:set)
25
25
 
26
- result = @cachedis.cachedis 'expensive-query' do
27
- "query"
28
- end
29
-
30
- result.should == "query".to_yaml
26
+ @cachedis.cachedis 'expensive-query' do
27
+ "query"
28
+ end
31
29
  end
32
30
  end
33
31
 
@@ -36,7 +34,7 @@ describe Cachedis do
36
34
  it 'sets them in redis' do
37
35
  with_no_cache
38
36
 
39
- @cachedis.redis_instance.should_receive(:expire).exactly(1).times
37
+ @cachedis.redis.should_receive(:expire).exactly(1).times
40
38
 
41
39
  @cachedis.cachedis 'name', :expire => 60 * 60 do
42
40
  end
@@ -46,7 +44,7 @@ describe Cachedis do
46
44
  context 'with an array of arguments' do
47
45
  it 'sets them in redis' do
48
46
  with_no_cache
49
- @cachedis.redis_instance.should_receive(:rename).exactly(1).times
47
+ @cachedis.redis.should_receive(:rename).exactly(1).times
50
48
 
51
49
  @cachedis.cachedis 'name', :rename => ['key', 'otherkey'] do
52
50
  end
@@ -1,15 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe CachedisInterface do
3
+ describe Cachedis::Interface do
4
4
  include HelperMethods
5
5
 
6
6
  describe 'when setting something' do
7
7
  it 'sets without errors' do
8
- @mock = mock(Cachedis)
9
- Cachedis.should_receive(:new).exactly(1).times.and_return(@mock)
8
+ @mock = mock(Cachedis::Cacher)
9
+ Cachedis::Cacher.should_receive(:new).exactly(1).times.and_return(@mock)
10
10
  @mock.stub!(:cachedis).and_return(['element', 'element 2'])
11
11
 
12
- CachedisInterface.cachedis 'expensive-query' do
12
+ Cachedis::Interface.cachedis 'expensive-query' do
13
13
  ['element', 'element 2']
14
14
  end
15
15
  end
@@ -11,6 +11,6 @@ module HelperMethods
11
11
 
12
12
  def with_cache(cache)
13
13
  @cachedis.redis.should_receive(:exists).exactly(1).times.and_return(true)
14
- @cachedis.redis.should_receive(:get).exactly(1).times.and_return(cache.to_yaml)
14
+ @cachedis.redis.should_receive(:get).exactly(1).times.and_return(cache)
15
15
  end
16
16
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - "Simon H\xC3\xB8rup Eskildsen"
@@ -72,6 +72,7 @@ files:
72
72
  - Gemfile.lock
73
73
  - README.md
74
74
  - Rakefile
75
+ - benchmarks/serialization.rb
75
76
  - cachedis.gemspec
76
77
  - lib/cachedis.rb
77
78
  - lib/cachedis/version.rb