diskcached 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/Benchmark.md +81 -0
  2. data/Gemfile +18 -0
  3. data/README.md +17 -0
  4. data/Rakefile +17 -0
  5. data/lib/diskcached.rb +159 -0
  6. metadata +102 -0
@@ -0,0 +1,81 @@
1
+ # Benchmarks
2
+
3
+ ## Comments
4
+
5
+ Diskcached wasn't designed to be a faster solution, just a simpler
6
+ one when compaired to Memcached. However, from these benchmarks,
7
+ it holds up will and even should provide slightly faster reads.
8
+
9
+
10
+ ## Ruby 1.8.7
11
+
12
+ **Warning:** Tests do not pass and therefore this isn't expected
13
+ to actaully work on ruby 1.8.7 at this point. I'm including the
14
+ benchmarks for it as an academic excercise.
15
+
16
+ ## Ruby 1.8.7
17
+
18
+ #### small string * 100000
19
+
20
+ <pre>
21
+ user system total real
22
+ diskcached set 3.260000 5.630000 8.890000 ( 21.660488)
23
+ memcached set 1.460000 1.280000 2.740000 ( 4.070615)
24
+ diskcached get 1.800000 0.720000 2.520000 ( 2.541142)
25
+ memcached get 1.160000 1.410000 2.570000 ( 3.609896)
26
+ </pre>
27
+
28
+ #### large hash * 100000
29
+
30
+ <pre>
31
+ user system total real
32
+ diskcached set 17.740000 8.140000 25.880000 ( 59.677151)
33
+ memcached set 13.840000 1.960000 15.800000 ( 18.235553)
34
+ diskcached get 11.860000 1.100000 12.960000 ( 13.003900)
35
+ memcached get 9.270000 1.880000 11.150000 ( 12.346795)
36
+ </pre>
37
+
38
+ ## Ruby 1.9.2p318
39
+
40
+ #### small string * 100000
41
+
42
+ <pre>
43
+ user system total real
44
+ diskcached set 3.370000 4.980000 8.350000 ( 20.467971)
45
+ memcached set 1.340000 1.300000 2.640000 ( 3.962354)
46
+ diskcached get 1.570000 0.350000 1.920000 ( 1.939561)
47
+ memcached get 1.330000 1.250000 2.580000 ( 3.604914)
48
+ </pre>
49
+
50
+ #### large hash * 100000
51
+
52
+ <pre>
53
+ user system total real
54
+ diskcached set 21.460000 6.950000 28.410000 ( 58.982826)
55
+ memcached set 16.510000 1.920000 18.430000 ( 20.862692)
56
+ diskcached get 16.570000 0.690000 17.260000 ( 17.306181)
57
+ memcached get 12.120000 1.630000 13.750000 ( 14.967464)
58
+ </pre>
59
+
60
+
61
+ ## Ruby 1.9.3p194
62
+
63
+ #### small string * 100000
64
+
65
+ <pre>
66
+ user system total real
67
+ diskcached set 3.520000 5.220000 8.740000 ( 21.928190)
68
+ memcached set 1.350000 1.480000 2.830000 ( 4.178223)
69
+ diskcached get 1.830000 0.370000 2.200000 ( 2.215781)
70
+ memcached get 1.570000 1.710000 3.280000 ( 4.662109)
71
+ </pre>
72
+
73
+ #### large hash * 100000
74
+
75
+ <pre>
76
+ user system total real
77
+ diskcached set 20.670000 7.170000 27.840000 ( 59.877671)
78
+ memcached set 15.310000 2.790000 18.100000 ( 21.132083)
79
+ diskcached get 14.950000 0.700000 15.650000 ( 15.720669)
80
+ memcached get 14.850000 1.840000 16.690000 ( 17.971276)
81
+ </pre>
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source :rubygems
2
+
3
+ group :development, :test do
4
+ gem 'rake'
5
+ end
6
+
7
+ group :development do
8
+ gem 'rdoc'
9
+
10
+ # for benchmark only
11
+ gem 'memcached'
12
+ end
13
+
14
+ group :test do
15
+ gem 'rspec'
16
+ gem 'simplecov', :require => false
17
+ end
18
+
@@ -0,0 +1,17 @@
1
+ # Diskcached
2
+
3
+ #### Test Status [![Build Status](https://secure.travis-ci.org/jmervine/diskcached.png?branch=master)](http://travis-ci.org/jmervine/diskcached)
4
+
5
+ #### Installation
6
+
7
+ gem install diskcached
8
+
9
+ #### [Documentation](http://jmervine.github.com/diskcached/doc/index.html)
10
+
11
+ #### [Coverage](http://jmervine.github.com/diskcached/coverage/index.html)
12
+
13
+ #### History
14
+
15
+ * 1.0.0 / 2012-07-03
16
+ * Pre-release version, widely untested outside of the actual tests.
17
+
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task :default => :spec
7
+
8
+
9
+ task :benchmark do
10
+ load './spec/benchmarks.rb'
11
+ end
12
+
13
+ task :package do
14
+ puts %x{ gem build diskcached.gemspec && (mkdir ./pkg; mv *.gem ./pkg/ ) }
15
+ end
16
+
17
+ # vim: syntax=ruby
@@ -0,0 +1,159 @@
1
+ # @author Joshua P. Mervine <joshua@mervine.net>
2
+ #
3
+ class Diskcached
4
+ # version for gem
5
+ VERSION = '1.0.1'
6
+
7
+ # disk location for cache store
8
+ attr_reader :store
9
+
10
+ # cache timeout
11
+ attr_reader :timeout
12
+
13
+ # time of last #garbage_collect_expired_caches
14
+ attr_reader :last_gc
15
+
16
+ # initialize object
17
+ # - set #store to passed or default ('/tmp/cache')
18
+ # - set #timeout to passed or default ('600')
19
+ # - set #last_gc to current time
20
+ # - run #ensure_store_directory
21
+ def initialize store="/tmp/cache", timeout=600
22
+ @store = store
23
+ @timeout = timeout
24
+ @last_gc = Time.now
25
+ ensure_store_directory
26
+ end
27
+
28
+ # return true if cache with 'key' is expired
29
+ def expired? key
30
+ mtime = read_cache_mtime(key)
31
+ return (mtime.nil? || mtime+timeout <= Time.now)
32
+ end
33
+
34
+ # expire cache with 'key'
35
+ def expire! key
36
+ File.delete( cache_file(key) ) if File.exists?( cache_file(key) )
37
+ end
38
+ alias :delete :expire!
39
+
40
+ # expire (delete) all caches in #store directory
41
+ def expire_all!
42
+ Dir[ File.join( store, '*.cache' ) ].each do |file|
43
+ File.delete(file)
44
+ end
45
+ end
46
+ alias :flush :expire_all!
47
+
48
+ # create and read cache with 'key'
49
+ # - run #garbage_collect_expired_caches
50
+ # - creates cache if it doesn't exist
51
+ # - reads cache if it exists
52
+ def cache key
53
+ garbage_collect_expired_caches
54
+ begin
55
+ if expired?(key)
56
+ content = Proc.new { yield }.call
57
+ set( key, content )
58
+ end
59
+ content ||= get( key )
60
+ return content
61
+ rescue LocalJumpError
62
+ return nil
63
+ end
64
+ end
65
+ alias :set_or_get :cache
66
+ alias :sog :cache
67
+
68
+ # set cache with 'key'
69
+ # - run #garbage_collect_expired_caches
70
+ # - creates cache if it doesn't exist
71
+ def set key, value
72
+ garbage_collect_expired_caches
73
+ begin
74
+ write_cache_file( key, Marshal::dump(value) )
75
+ return true
76
+ rescue
77
+ return false
78
+ end
79
+ end
80
+ alias :add :set
81
+ alias :replace :set
82
+
83
+ # get cache with 'key'
84
+ # - reads cache if it exists and isn't expired
85
+ # or raises Diskcache::NotFound
86
+ # - if 'key' is an Array returns only keys
87
+ # which exist and aren't expired, it raises
88
+ # Diskcache::NotFound if none are available
89
+ def get key
90
+ garbage_collect_expired_caches
91
+ begin
92
+ if key.is_a? Array
93
+ hash = {}
94
+ key.each do |k|
95
+ hash[k] = Marshal::load(read_cache_file(k)) unless expired?(k)
96
+ end
97
+ return hash unless hash.empty?
98
+ else
99
+ return Marshal::load(read_cache_file(key)) unless expired?(key)
100
+ end
101
+ raise Diskcached::NotFound
102
+ rescue
103
+ raise Diskcached::NotFound
104
+ end
105
+ end
106
+
107
+ # returns path to cache file with 'key'
108
+ def cache_file key
109
+ File.join( store, key+".cache" )
110
+ end
111
+
112
+
113
+ private
114
+ # delete all expired caches every #timeout seconds
115
+ # on being called
116
+ def garbage_collect_expired_caches
117
+ if last_gc+timeout <= Time.now
118
+ Dir[ File.join( store, "*.cache" ) ].each do |f|
119
+ if (File.mtime(f)+timeout) <= Time.now
120
+ File.delete(f)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ # creates the actual cache file
127
+ def write_cache_file key, content
128
+ f = File.open( cache_file(key), "w+" )
129
+ f.flock(File::LOCK_EX)
130
+ f.write( content )
131
+ f.close
132
+ return content
133
+ end
134
+
135
+ # reads the actual cache file
136
+ def read_cache_file key
137
+ f = File.open( cache_file(key), "r" )
138
+ f.flock(File::LOCK_SH)
139
+ out = f.read
140
+ f.close
141
+ return out
142
+ end
143
+
144
+ # returns mtime of cache file or nil if
145
+ # file doesn't exist
146
+ def read_cache_mtime key
147
+ return nil unless File.exists?(cache_file(key))
148
+ File.mtime( cache_file(key) )
149
+ end
150
+
151
+ # creates #store directory if it doesn't exist
152
+ def ensure_store_directory
153
+ Dir.mkdir( store ) unless File.directory?( store )
154
+ end
155
+
156
+ class NotFound < Exception
157
+ end
158
+
159
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: diskcached
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joshua Mervine
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: simplecov
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rdoc
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Simple disk cache for things like Sinatra which is implemented much like
63
+ Memcached in hopes that in some cases they're interchangeable.
64
+ email:
65
+ - joshua@mervine.net
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - lib/diskcached.rb
71
+ - README.md
72
+ - Benchmark.md
73
+ - Gemfile
74
+ - Rakefile
75
+ homepage: http://jmervine.github.com/diskcached/
76
+ licenses: []
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ segments:
88
+ - 0
89
+ hash: -4576607150070484010
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: 1.3.6
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 1.8.24
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: Simple disk cache
102
+ test_files: []