oria 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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 KVS and asynchronously writes the in-memory data to YAML files.
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 a provided as a Gem. Use the following command to install it:
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
- 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
131
- the current version information, it's a very young project, and any contribution is welcome.
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.2
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
- # require 'rubygems'
4
- # require 'oria'
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 #"Usage: oria start|stop|restart"
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 write_hash
46
- @@write_hash ||= proc do
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
- EventMachine.defer(Oria::Server.write_hash)
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.1"
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-22}
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
- "LICENSE",
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.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.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.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.2
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-22 00:00:00 -05:00
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