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.
- data/Benchmark.md +81 -0
- data/Gemfile +18 -0
- data/README.md +17 -0
- data/Rakefile +17 -0
- data/lib/diskcached.rb +159 -0
- metadata +102 -0
data/Benchmark.md
ADDED
@@ -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
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Diskcached
|
2
|
+
|
3
|
+
#### Test Status [](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
|
+
|
data/Rakefile
ADDED
@@ -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
|
data/lib/diskcached.rb
ADDED
@@ -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: []
|