diskcached 1.0.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.
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: []