oria 0.0.2 → 0.0.3
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/.gitignore +1 -0
- data/README.markdown +61 -5
- data/VERSION +1 -1
- data/benchmarks/mysql_table.sql +26 -0
- data/benchmarks/redis_v_oria.rb +33 -0
- data/benchmarks/sequel_v_oria.rb +39 -0
- data/benchmarks/sqlite_v_oria.rb +45 -0
- data/bin/oria +7 -4
- data/lib/oria/server.rb +17 -12
- data/oria.gemspec +17 -7
- metadata +7 -2
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg/*
|
data/README.markdown
CHANGED
@@ -3,12 +3,12 @@ Oria
|
|
3
3
|
|
4
4
|
Oria (oh-rye-uh) is an in-memory, Ruby-based Key-Value Store. It's designed to handle moderate amounts of data quickly
|
5
5
|
and easily without causing deployment issues or server headaches. It uses EventMachine to provide a networked interface
|
6
|
-
to a semi-persistent
|
6
|
+
to a semi-persistent store and asynchronously writes the in-memory data to YAML files.
|
7
7
|
|
8
8
|
Installation
|
9
9
|
-
|
10
10
|
|
11
|
-
Oria is
|
11
|
+
Oria is provided as a Gem. Use the following command to install it:
|
12
12
|
|
13
13
|
gem install oria --source http://gemcutter.org
|
14
14
|
|
@@ -41,7 +41,7 @@ untested, so please test it heavily before deploying, and _report any issues you
|
|
41
41
|
Usage
|
42
42
|
-
|
43
43
|
|
44
|
-
Okay, now for the fun part. Oria behaves (mostly) like a Hash - you could say that it responds to 2/3 of @wycats' Moneta
|
44
|
+
Okay, now for the fun part. Oria behaves (mostly) like a Hash - you could say that it responds to 2/3 of [@wycats](http://github.com/wycats)' Moneta
|
45
45
|
plugin. Specifically, it responds to the following Hash methods:
|
46
46
|
|
47
47
|
[]=(value) Set a key to ... something.
|
@@ -117,6 +117,9 @@ Let's try it out:
|
|
117
117
|
Oria.app_key = "my_app_1"
|
118
118
|
Oria[:foo] #=> "bar"
|
119
119
|
|
120
|
+
That's it! I hope you enjoy Oria, and please let me know if you find any issues or have any trouble. As you will no doubt see from
|
121
|
+
the current version information, it's a very young project, and any contribution is welcome.
|
122
|
+
|
120
123
|
Dependencies
|
121
124
|
-
|
122
125
|
|
@@ -127,7 +130,60 @@ It also needs [EventMachine](http://github.com/eventmachine/eventmachine) to do
|
|
127
130
|
UDP sockets, and spent a lifetime on this. But EventMachine is seriously, seriously, seriously awesome, and works very well
|
128
131
|
without me writing an insane amount of code I couldn't write very well anyway. Check it out and see for yourself.
|
129
132
|
|
130
|
-
|
131
|
-
|
133
|
+
Warnings
|
134
|
+
-
|
135
|
+
|
136
|
+
Oria is weak in a few places. First, it forks all over the place with no regard for the consequences. Someday I'm going to upgrade it
|
137
|
+
to use Daemons, but not right now. In general, the forking is dangerous and clumsy.
|
138
|
+
|
139
|
+
Also, Oria's auto-start feature relies on `sleep`. In fact, Oria relies on `sleep` in more than one place. _This is terrible_ and I
|
140
|
+
want to fix it someday. But I also want to get the code out there so people can start breaking it and tell me where it breaks.
|
141
|
+
|
142
|
+
Which means: **please report any problems you have using the [Github issue tracking](http://github.com/flipsasser/oria/issues)!**
|
143
|
+
|
144
|
+
Benchmarks
|
145
|
+
-
|
146
|
+
|
147
|
+
I've run some benchmarks comparing Oria to Redis. It's not pretty:
|
148
|
+
|
149
|
+
user system total real
|
150
|
+
Redis (write): 0.050000 0.020000 0.070000 ( 0.115850)
|
151
|
+
Oria (write): 0.140000 0.110000 0.250000 ( 1.267912)
|
152
|
+
Redis (read): 0.070000 0.020000 0.090000 ( 0.145078)
|
153
|
+
Oria (read): 0.150000 0.110000 0.260000 ( 1.247791)
|
154
|
+
|
155
|
+
As you can see, Oria is about 10x slower than Redis on my development computer. Even worse, if you run the benchmark like so:
|
156
|
+
|
157
|
+
ruby redis_v_oria.rb 10000
|
158
|
+
|
159
|
+
Oria's server will fail to fulfill all of those requests. Scary. Clearly, it needs some serious improvement. Oria will never be
|
160
|
+
as performant as something like Redis - it's not meant to be (plus it's written in Ruby, not C). But it could use some reduction
|
161
|
+
in overhead, and any help is welcome.
|
162
|
+
|
163
|
+
But I knew Oria wouldn't compete with Redis. What about MySQL?
|
164
|
+
|
165
|
+
user system total real
|
166
|
+
MySQL (write): 0.270000 0.030000 0.300000 ( 0.445586)
|
167
|
+
Oria (write): 0.170000 0.120000 0.290000 ( 1.676674)
|
168
|
+
MySQL (read): 0.310000 0.020000 0.330000 ( 0.484944)
|
169
|
+
Oria (read): 0.120000 0.120000 0.240000 ( 1.616851)
|
170
|
+
|
171
|
+
Ew. Oria is consistently about 4x slower than MySQL. But check this out: I removed persistence, and here are the new benchmarks:
|
172
|
+
|
173
|
+
user system total real
|
174
|
+
Redis (write): 0.040000 0.020000 0.060000 ( 0.113882)
|
175
|
+
Oria (write): 0.130000 0.100000 0.230000 ( 0.396776)
|
176
|
+
Redis (read): 0.070000 0.020000 0.090000 ( 0.145068)
|
177
|
+
Oria (read): 0.130000 0.100000 0.230000 ( 0.395410)
|
178
|
+
|
179
|
+
That's getting competitive. How about MySQL?
|
180
|
+
|
181
|
+
user system total real
|
182
|
+
MySQL (write): 0.270000 0.030000 0.300000 ( 0.453413)
|
183
|
+
Oria (write): 0.150000 0.110000 0.260000 ( 0.430725)
|
184
|
+
MySQL (read): 0.320000 0.030000 0.350000 ( 0.484978)
|
185
|
+
Oria (read): 0.100000 0.100000 0.200000 ( 0.373431)
|
186
|
+
|
187
|
+
Oh snap! Oria outperforms MySQL when persistence is disabled. So I'll have to refactor the code.
|
132
188
|
|
133
189
|
Copyright (c) 2009 Flip Sasser, released under the MIT license
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
@@ -0,0 +1,26 @@
|
|
1
|
+
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
2
|
+
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
3
|
+
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
4
|
+
/*!40101 SET NAMES utf8 */;
|
5
|
+
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
6
|
+
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
7
|
+
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
8
|
+
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
9
|
+
|
10
|
+
DROP TABLE IF EXISTS `oria_test`;
|
11
|
+
|
12
|
+
CREATE TABLE `oria_test` (
|
13
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
14
|
+
`key` varchar(32) DEFAULT NULL,
|
15
|
+
`value` varchar(128) DEFAULT NULL,
|
16
|
+
PRIMARY KEY (`id`),
|
17
|
+
UNIQUE KEY `key` (`key`)
|
18
|
+
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
|
19
|
+
|
20
|
+
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
21
|
+
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
22
|
+
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
23
|
+
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
24
|
+
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
25
|
+
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
26
|
+
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'redis'
|
3
|
+
require '../lib/oria'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
redis = Redis.new
|
7
|
+
n = (ARGV.shift || 1000).to_i
|
8
|
+
|
9
|
+
Benchmark.bm(15) do |bm|
|
10
|
+
bm.report("Redis (write):") do
|
11
|
+
n.times do
|
12
|
+
redis['foo'] = 'bar'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
bm.report("Oria (write):") do
|
17
|
+
n.times do
|
18
|
+
Oria['foo'] = 'bar'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
bm.report("Redis (read):") do
|
23
|
+
n.times do
|
24
|
+
foo = redis['foo']
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
bm.report("Oria (read):") do
|
29
|
+
n.times do
|
30
|
+
foo = Oria['foo']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sequel'
|
3
|
+
require '../lib/oria'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
DB = Sequel.connect('mysql://root@localhost/oria_test')
|
7
|
+
n = (ARGV.shift || 1000).to_i
|
8
|
+
|
9
|
+
Benchmark.bm(15) do |bm|
|
10
|
+
bm.report("MySQL (write):") do
|
11
|
+
table = DB[:oria_test]
|
12
|
+
n.times do
|
13
|
+
if foo = table[:key => 'foo']
|
14
|
+
foo.update(:value => 'bar')
|
15
|
+
else
|
16
|
+
table.insert(:key => 'foo', :value => 'bar')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
bm.report("Oria (write):") do
|
22
|
+
n.times do
|
23
|
+
Oria['foo'] = 'bar'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
bm.report("MySQL (read):") do
|
28
|
+
table = DB[:oria_test]
|
29
|
+
n.times do
|
30
|
+
foo = table[:key => 'foo']
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
bm.report("Oria (read):") do
|
35
|
+
n.times do
|
36
|
+
foo = Oria['foo']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sequel'
|
3
|
+
require '../lib/oria'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
DB = Sequel.sqlite
|
7
|
+
DB.create_table :oria_test do
|
8
|
+
primary_key :id
|
9
|
+
String :key
|
10
|
+
String :value
|
11
|
+
end
|
12
|
+
|
13
|
+
n = (ARGV.shift || 1000).to_i
|
14
|
+
|
15
|
+
Benchmark.bm(16) do |bm|
|
16
|
+
bm.report("SQLite3 (write):") do
|
17
|
+
table = DB[:oria_test]
|
18
|
+
n.times do
|
19
|
+
if foo = table[:key => 'foo']
|
20
|
+
foo.update(:value => 'bar')
|
21
|
+
else
|
22
|
+
table.insert(:key => 'foo', :value => 'bar')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
bm.report("Oria (write):") do
|
28
|
+
n.times do
|
29
|
+
Oria['foo'] = 'bar'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
bm.report("SQLite3 (read):") do
|
34
|
+
table = DB[:oria_test]
|
35
|
+
n.times do
|
36
|
+
foo = table[:key => 'foo']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
bm.report("Oria (read):") do
|
41
|
+
n.times do
|
42
|
+
foo = Oria['foo']
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/bin/oria
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'optparse'
|
3
|
-
|
4
|
-
|
5
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'oria'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'oria'
|
5
|
+
# require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'oria'))
|
6
6
|
|
7
7
|
module OriaCommand
|
8
8
|
def self.go
|
@@ -15,7 +15,7 @@ module OriaCommand
|
|
15
15
|
stop
|
16
16
|
start
|
17
17
|
else
|
18
|
-
puts parser
|
18
|
+
puts parser
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -29,6 +29,9 @@ module OriaCommand
|
|
29
29
|
opts.on('-h', '--host [IP]', 'The hostname or IP Oria should listen on.') do |host|
|
30
30
|
@options[:host] = port
|
31
31
|
end
|
32
|
+
opts.on('-d', '--debug', 'Log output to /tmp/oria.log') do |debug|
|
33
|
+
@options[:debug] = true
|
34
|
+
end
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
data/lib/oria/server.rb
CHANGED
@@ -3,10 +3,16 @@ require 'tmpdir'
|
|
3
3
|
module Oria
|
4
4
|
class Server < EventMachine::Connection
|
5
5
|
class << self
|
6
|
+
@@timer = nil
|
7
|
+
|
6
8
|
def debug?
|
7
9
|
@@debug
|
8
10
|
end
|
9
11
|
|
12
|
+
def log(value, app_key = nil)
|
13
|
+
logger.debug("#{"#{app_key}: " if app_key}#{value}") if debug?
|
14
|
+
end
|
15
|
+
|
10
16
|
def logger
|
11
17
|
require 'logger'
|
12
18
|
@@logger ||= Logger.new(log_file, 0, 100 * 1024 * 1024)
|
@@ -42,11 +48,14 @@ module Oria
|
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
45
|
-
def
|
46
|
-
@@
|
51
|
+
def store_hash(app_key)
|
52
|
+
@@timer.cancel if @@timer
|
53
|
+
@@timer = EventMachine::Timer.new(10) do
|
54
|
+
log "Writing changes to disk", app_key
|
47
55
|
File.open(yaml_store, 'w') do |store|
|
48
56
|
store.puts YAML.dump(@@servers)
|
49
57
|
end
|
58
|
+
@@timer = nil
|
50
59
|
end
|
51
60
|
end
|
52
61
|
|
@@ -69,11 +78,11 @@ module Oria
|
|
69
78
|
end
|
70
79
|
|
71
80
|
def post_init
|
72
|
-
log "Client connected"
|
81
|
+
Oria::Server.log "Client connected"
|
73
82
|
end
|
74
83
|
|
75
84
|
def receive_data(data)
|
76
|
-
log "Responding to #{data}"
|
85
|
+
Oria::Server.log "Responding to #{data}"
|
77
86
|
data = data.split(' ')
|
78
87
|
method = data.shift
|
79
88
|
data = JSON.parse(data.join(' '))
|
@@ -98,10 +107,12 @@ module Oria
|
|
98
107
|
end
|
99
108
|
if defined?(response)
|
100
109
|
response = JSON.generate({:response => response})
|
101
|
-
log "Sending response: #{response}"
|
110
|
+
Oria::Server.log "Sending response: #{response}"
|
111
|
+
Oria::Server.store_hash(@app_key)
|
102
112
|
send_data response
|
103
113
|
end
|
104
|
-
|
114
|
+
rescue JSON::ParserError
|
115
|
+
send_data "Invalid request"
|
105
116
|
end
|
106
117
|
|
107
118
|
def unbind
|
@@ -112,12 +123,6 @@ module Oria
|
|
112
123
|
@hash ||= @@servers[@app_key || 'default'] ||= {}
|
113
124
|
end
|
114
125
|
|
115
|
-
def log(value)
|
116
|
-
if Oria::Server.debug?
|
117
|
-
Oria::Server.logger.debug(value)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
126
|
def random_key
|
122
127
|
chars = ['a'..'z', 'A'..'Z', 0..9].map(&:to_a).flatten
|
123
128
|
max = [hash.length, 2].max
|
data/oria.gemspec
CHANGED
@@ -5,13 +5,17 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{oria}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Flip Sasser"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-23}
|
13
13
|
s.default_executable = %q{oria}
|
14
|
-
s.description = %q{
|
14
|
+
s.description = %q{
|
15
|
+
Oria (oh-rye-uh) is an in-memory, Ruby-based Key-Value store. It's designed to handle moderate amounts of data quickly
|
16
|
+
and easily without causing deployment issues or server headaches. It uses EventMachine to provide a networked interface
|
17
|
+
to a semi-persistent KVS and asynchronously writes the in-memory data to YAML files.
|
18
|
+
}
|
15
19
|
s.email = %q{flip@x451.com}
|
16
20
|
s.executables = ["oria"]
|
17
21
|
s.extra_rdoc_files = [
|
@@ -19,15 +23,21 @@ Gem::Specification.new do |s|
|
|
19
23
|
"README.markdown"
|
20
24
|
]
|
21
25
|
s.files = [
|
22
|
-
"
|
26
|
+
".gitignore",
|
27
|
+
"LICENSE",
|
23
28
|
"README.markdown",
|
24
29
|
"Rakefile",
|
25
30
|
"VERSION",
|
31
|
+
"benchmarks/mysql_table.sql",
|
32
|
+
"benchmarks/redis_v_oria.rb",
|
33
|
+
"benchmarks/sequel_v_oria.rb",
|
34
|
+
"benchmarks/sqlite_v_oria.rb",
|
26
35
|
"bin/oria",
|
27
36
|
"lib/oria.rb",
|
28
37
|
"lib/oria/client.rb",
|
29
38
|
"lib/oria/errors.rb",
|
30
39
|
"lib/oria/server.rb",
|
40
|
+
"oria.gemspec",
|
31
41
|
"spec/oria_spec.rb",
|
32
42
|
"spec/rcov.opts",
|
33
43
|
"spec/spec.opts",
|
@@ -49,14 +59,14 @@ Gem::Specification.new do |s|
|
|
49
59
|
|
50
60
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
61
|
s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.10"])
|
52
|
-
s.add_runtime_dependency(%q<json>, [">= 2.0
|
62
|
+
s.add_runtime_dependency(%q<json>, [">= 1.2.0"])
|
53
63
|
else
|
54
64
|
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
55
|
-
s.add_dependency(%q<json>, [">= 2.0
|
65
|
+
s.add_dependency(%q<json>, [">= 1.2.0"])
|
56
66
|
end
|
57
67
|
else
|
58
68
|
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
59
|
-
s.add_dependency(%q<json>, [">= 2.0
|
69
|
+
s.add_dependency(%q<json>, [">= 1.2.0"])
|
60
70
|
end
|
61
71
|
end
|
62
72
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oria
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Flip Sasser
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-23 00:00:00 -05:00
|
13
13
|
default_executable: oria
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,10 +42,15 @@ extra_rdoc_files:
|
|
42
42
|
- LICENSE
|
43
43
|
- README.markdown
|
44
44
|
files:
|
45
|
+
- .gitignore
|
45
46
|
- LICENSE
|
46
47
|
- README.markdown
|
47
48
|
- Rakefile
|
48
49
|
- VERSION
|
50
|
+
- benchmarks/mysql_table.sql
|
51
|
+
- benchmarks/redis_v_oria.rb
|
52
|
+
- benchmarks/sequel_v_oria.rb
|
53
|
+
- benchmarks/sqlite_v_oria.rb
|
49
54
|
- bin/oria
|
50
55
|
- lib/oria.rb
|
51
56
|
- lib/oria/client.rb
|