iodine 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a37969c5d9707236f1d87fcc548a442908d01fd
4
- data.tar.gz: 450f40d62e72cf9a575188ecd62509fc1429a771
3
+ metadata.gz: 3ae7877010acc419eed5fe07927ba5bbe3a58c4d
4
+ data.tar.gz: af9499644636b46887940f5328f0204f1f654e42
5
5
  SHA512:
6
- metadata.gz: 6c3fb1a3627926510480b73a3468940c1e436c15e60c295c508003beeb8997120047a8d483df76e6bfdc0e295eb199e2222c5713c11b33da0ae97ef316e39560
7
- data.tar.gz: 67291bdfbcf83e45f03aae739e17ff5b511746ef8e7aa4ba99622ecb5306d1a9c9558cef8867e93fd5469f00c031ed70a64355231f5b0f7baff0f4037c480d4e
6
+ metadata.gz: 30225e2179f074851eeb497a03e57a1d7e142b6f85c367b28efd99a4af3f4648fef1655a0fe599de95c05826931c726d4dc2fc4fa02597efce065b51d380a755
7
+ data.tar.gz: 9b28f309443e33f15ea48993ba4ff8a74c83580ad2a24957c2678b4bca333f5c50e011673613f13bc7f8f8434366e043b48d648e999a0c44e9518a9e6450370d
@@ -8,6 +8,14 @@ Please notice that this change log contains changes for upcoming releases as wel
8
8
 
9
9
  ***
10
10
 
11
+ #### Change log v.0.4.1
12
+
13
+ **Fix**: postpone warmup in fear of abuse and collisions when using `fork`. i.e., during warmup, an application might perform actions that conflict with `fork` and worker initialization, such as creating a database connection pool during warmup, or maybe spawning a thread. Now `warmup` is postponed until *after* worker processes are up and running, resulting in a per-process warmup rather than a per-cluster warmup.
14
+
15
+ **Fix** move the `rake-compiler` dependency to "development" instead of "runtime". Credit to Luis Lavena (@luislavena) for exposing the issue (#19).
16
+
17
+ ***
18
+
11
19
  #### Change log v.0.4.0
12
20
 
13
21
  **Braking change**: Some of the API was changed / updated, hopefully simplified.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Iodine - HTTP / Websocket Server & EventMachine alternative: C kqueue/epoll extension
1
+ # iodine - HTTP / Websocket Server with Pub/Sub support, optimized for Ruby MRI on Linux / BSD
2
2
  [![Logo](https://github.com/boazsegev/iodine/raw/master/logo.png)](https://github.com/boazsegev/iodine)
3
3
 
4
4
  [![Build Status](https://travis-ci.org/boazsegev/iodine.svg?branch=master)](https://travis-ci.org/boazsegev/iodine)
@@ -6,21 +6,24 @@
6
6
  [![Inline docs](http://inch-ci.org/github/boazsegev/iodine.svg?branch=master)](http://www.rubydoc.info/github/boazsegev/iodine/master/frames)
7
7
  [![GitHub](https://img.shields.io/badge/GitHub-Open%20Source-blue.svg)](https://github.com/boazsegev/iodine)
8
8
 
9
- Iodine is a fast concurrent web server for real-time Ruby applications, with native support for Websockets, Pub/Sub, static file service, HTTP/1.1 and Redis Pub/Sub scaling (2 connections per Iodine process).
9
+ Iodine is a fast concurrent web server for real-time Ruby applications, with native support for:
10
10
 
11
- Iodine also supports custom protocol authoring, making Object Oriented **Network Services** easy to write.
11
+ * Websockets;
12
+ * Pub/Sub (with optional Redis Pub/Sub scaling);
13
+ * Static file service (with automatic `gzip` support for pre-compressed versions);
14
+ * HTTP/1.1 keep-alive and pipelining;
15
+ * Asynchronous event scheduling and timers;
16
+ * Client connectivity (attach client sockets to make them evented);
17
+ * Custom protocol authoring;
18
+ * and more!
12
19
 
13
20
  Iodine is an **evented** framework with a simple API that builds off the low level [C code library facil.io](https://github.com/boazsegev/facil.io) with support for **epoll** and **kqueue** - this means that:
14
21
 
15
- * Iodine can handle **thousands of concurrent connections** (tested with more then 20K connections).
16
-
17
- That's right, Iodine isn't subject to the 1024 connection limit imposed by native Ruby and `select`/`poll` based applications.
18
-
19
- This makes Iodine ideal for writing HTTP/2 and Websocket servers (which is what started this whole thing).
22
+ * Iodine can handle **thousands of concurrent connections** (tested with more then 20K connections)!
20
23
 
21
24
  * Iodine supports only **Linux/Unix** based systems (i.e. OS X, Ubuntu, FreeBSD etc'), which are ideal for evented IO (while Windows and Solaris are better at IO *completion* events, which are totally different).
22
25
 
23
- Iodine is a C extension for Ruby, developed for Ruby MRI 2.2.2 and up... it should support the whole Ruby 2.0 MRI family, but Rack requires Ruby 2.2.2, and so Iodine matches this requirement.
26
+ Iodine is a C extension for Ruby, developed and optimized for Ruby MRI 2.2.2 and up... it should support the whole Ruby 2.0 MRI family, but Rack requires Ruby 2.2.2, and so iodine matches this requirement.
24
27
 
25
28
  ## Iodine::Rack == a fast and powerful HTTP + Websockets server with native Pub/Sub
26
29
 
@@ -28,11 +31,11 @@ Iodine includes a light and fast HTTP and Websocket server written in C that was
28
31
 
29
32
  With `Iodine.listen2http` it's possible to run multiple HTTP applications in addition to (or instead of) the default `Iodine::Rack` HTTP service.
30
33
 
31
- Iodine also supports native process cluster Pub/Sub and a native RedisEngins to easily scale Iodine's Pub/Sub horizontally.
34
+ Iodine also supports native process cluster Pub/Sub and a native RedisEngins to easily scale iodine's Pub/Sub horizontally.
32
35
 
33
36
  ### Running the web server
34
37
 
35
- Using the Iodine server is easy, simply add Iodine as a gem to your Rack application:
38
+ Using the iodine server is easy, simply add iodine as a gem to your Rack application:
36
39
 
37
40
  ```ruby
38
41
  gem 'iodine', '~>0.4'
@@ -40,7 +43,7 @@ gem 'iodine', '~>0.4'
40
43
 
41
44
  Iodine will calculate, when possible, a good enough default concurrency model for lightweight applications... this might not fit your application if you use heavier database access or other blocking calls.
42
45
 
43
- To get the most out of Iodine, consider the amount of CPU cores available and the concurrency level the application requires.
46
+ To get the most out of iodine, consider the amount of CPU cores available and the concurrency level the application requires.
44
47
 
45
48
  The common model of 16 threads and 4 processes can be easily adopted:
46
49
 
@@ -52,7 +55,7 @@ bundler exec iodine -p $PORT -t 16 -w 4
52
55
 
53
56
  Iodine supports an internal static file service that bypasses the Ruby layer and serves static files directly from "C-land".
54
57
 
55
- This means that Iodine won't lock Ruby's GVL when sending static files. The files will be sent directly, allowing for true native concurrency.
58
+ This means that iodine won't lock Ruby's GVL when sending static files. The files will be sent directly, allowing for true native concurrency.
56
59
 
57
60
  Since the Ruby layer is unaware of these requests, logging can be performed by turning iodine's logger on.
58
61
 
@@ -86,7 +89,7 @@ Ruby can leverage static file support (if enabled) by using the `X-Sendfile` hea
86
89
 
87
90
  This allows Ruby to send very large files using a very small memory footprint, as well as (when possible) leveraging the `sendfile` system call.
88
91
 
89
- i.e. (example `config.ru` for Iodine):
92
+ i.e. (example `config.ru` for iodine):
90
93
 
91
94
  ```ruby
92
95
  app = proc do |env|
@@ -108,17 +111,31 @@ run app
108
111
 
109
112
  Go to [localhost:3000/source](http://localhost:3000/source) to download the `config.ru` file using the `X-Sendfile` extension.
110
113
 
114
+ #### Pre-Compressed assets / files
115
+
116
+ Simply `gzip` your static files and iodine will automatically recognize and send the `gz` version if the client (browser) supports the `gzip` transfer-encoding.
117
+
118
+ For example, to offer a compressed version of `style.css`, run (in the terminal):
119
+
120
+ $ gzip -k -9 style.css
121
+
122
+ Now, you will have two files in your folder, `style.css` and `style.css.gz`.
123
+
124
+ When a browser that supports compressed encoding (which is most browsers) requests the file, iodine will recognize that a pre-compressed option exists and will prefer the `gzip` compressed version.
125
+
126
+ It's as easy as that. No extra code required.
127
+
111
128
  ### Special HTTP `Upgrade` support
112
129
 
113
- Iodine's HTTP server includes special support for the Upgrade directive using Rack's `env` Hash, allowing the application to focus on services and data while Iodine takes care of the network layer.
130
+ Iodine's HTTP server includes special support for the Upgrade directive using Rack's `env` Hash, allowing the application to focus on services and data while iodine takes care of the network layer.
114
131
 
115
- Upgrading an HTTP connection can be performed either using Iodine's Websocket Protocol support with `env['upgrade.websocket']` or by implementing your own protocol directly over the TCP/IP layer - be it a websocket flavor or something completely different - using `env['upgrade.tcp']`.
132
+ Upgrading an HTTP connection can be performed either using iodine's Websocket Protocol support with `env['upgrade.websocket']` or by implementing your own protocol directly over the TCP/IP layer - be it a websocket flavor or something completely different - using `env['upgrade.tcp']`.
116
133
 
117
134
  #### Websockets
118
135
 
119
- When an HTTP Upgrade request is received, Iodine will set the Rack Hash's upgrade property to `true`, so that: `env[upgrade.websocket?] == true`
136
+ When an HTTP Upgrade request is received, iodine will set the Rack Hash's upgrade property to `true`, so that: `env[upgrade.websocket?] == true`
120
137
 
121
- To "upgrade" the HTTP request to the Websockets protocol, simply provide Iodine with a Websocket Callback Object instance or class: `env['upgrade.websocket'] = MyWebsocketClass` or `env['upgrade.websocket'] = MyWebsocketClass.new(args)`
138
+ To "upgrade" the HTTP request to the Websockets protocol, simply provide iodine with a Websocket Callback Object instance or class: `env['upgrade.websocket'] = MyWebsocketClass` or `env['upgrade.websocket'] = MyWebsocketClass.new(args)`
122
139
 
123
140
  Iodine will adopt the object, providing it with network functionality (methods such as `write`, `each`, `defer` and `close` will become available) and invoke it's callbacks on network events.
124
141
 
@@ -126,7 +143,7 @@ Here is a simple chatroom example we can run in the terminal (`irb`) or easily p
126
143
 
127
144
  ```ruby
128
145
  require 'iodine'
129
- class WebsocketEcho
146
+ class WebsocketChat
130
147
  def on_open
131
148
  # Pub/Sub directly to the client (or use a block to process the messages)
132
149
  subscribe channel: :chat
@@ -140,7 +157,7 @@ class WebsocketEcho
140
157
  end
141
158
  Iodine::Rack.app= Proc.new do |env|
142
159
  if env['upgrade.websocket?'.freeze] && env["HTTP_UPGRADE".freeze] =~ /websocket/i.freeze
143
- env['upgrade.websocket'.freeze] = WebsocketEcho # or: WebsocketEcho.new
160
+ env['upgrade.websocket'.freeze] = WebsocketChat # or: WebsocketChat.new
144
161
  [0,{}, []] # It's possible to set cookies for the response.
145
162
  else
146
163
  [200, {"Content-Length" => "12"}, ["Welcome Home"] ]
@@ -157,6 +174,48 @@ Iodine::Rack.public = "www/public"
157
174
  Iodine.start
158
175
  ```
159
176
 
177
+ #### Native Pub/Sub with *optional* Redis scaling
178
+
179
+ Iodine's core, `facil.io` offers a native Pub/Sub implementation. The implementation is totally native to iodine, it covers the whole process cluster and it can be easily scaled by using Redis (which isn't required except for horizontal scaling).
180
+
181
+ Here's an example that adds horizontal scaling to the chat application in the previous example, so that Pub/Sub messages are published across many machines at once:
182
+
183
+ ```ruby
184
+ require 'uri'
185
+ # initialize the Redis engine for each iodine process.
186
+ if ENV["REDIS_URL"]
187
+ uri = URI(ENV["REDIS_URL"])
188
+ Iodine.default_pubsub = Iodine::PubSub::RedisEngine.new(uri.host, uri.port, 0, uri.password)
189
+ else
190
+ puts "* No Redis, it's okay, pub/sub will still run on the whole process cluster."
191
+ end
192
+
193
+ # ... the rest of the application remain unchanged.
194
+ ```
195
+
196
+ The new Redis client can also be used for asynchronous Redis command execution. i.e.:
197
+
198
+ ```ruby
199
+ if(Iodine.default_pubsub.is_a? Iodine::PubSub::RedisEngine)
200
+ # Ask Redis about all it's client connections and print out the reply.
201
+ Iodine.default_pubsub.send("CLIENT LIST") { |reply| puts reply }
202
+ end
203
+ ```
204
+
205
+ **Details and Limitations:**
206
+
207
+ * Iodine does not use a Hash table for the Pub/Sub channels, it uses a [4 bit trie](https://en.wikipedia.org/wiki/Trie).
208
+
209
+ The cost is higher memory consumption per channel and a limitation of 1024 bytes per channel name (shorter names are better).
210
+
211
+ The bonus is high lookup times, zero chance of channel conflicts and an optimized preference for shared prefix channels (i.e. "user:1", "user:2"...).
212
+
213
+ Another added bonus is pattern publishing (is addition to pattern subscriptions) which isn't available when using Redis (since Redis doesn't support this feature).
214
+
215
+ * Iodine's Redis client does *not* support multiple databases. This is both becasue [database scoping is ignored by Redis during pub/sub](https://redis.io/topics/pubsub#database-amp-scoping) and because [Redis Cluster doesn't support multiple databases](https://redis.io/topics/cluster-spec). This indicated that multiple database support just isn't worth the extra effort.
216
+
217
+ * The iodine Redis client will use two Redis connections per process (one for subscriptions and the other for publishing and commands). Both connections will be automatically re-established if timeouts or errors occur.
218
+
160
219
  #### TCP/IP (raw) sockets
161
220
 
162
221
  Upgrading to a custom protocol (i.e., in order to implement your own Websocket protocol with special extensions) is performed almost the same way, using `env['upgrade.tcp']`. In the following (terminal) example, we'll use an echo server without direct socket echo:
@@ -188,7 +247,7 @@ This design has a number of benefits, some of them related to better IO handling
188
247
 
189
248
  Iodine::Rack imposes a few restrictions for performance and security reasons, such as that the headers (both sending and receiving) must be less than 8Kb in size. These restrictions shouldn't be an issue and are similar to limitations imposed by Apache.
190
249
 
191
- Of course, if you still want to use Rack's `hijack` API, Iodine will support you - but be aware that you will need to implement your own reactor and thread pool for any sockets you hijack, as well as a socket buffer for non-blocking `write` operations (why do that when you can write a protocol object and have the main reactor manage the socket?).
250
+ Of course, if you still want to use Rack's `hijack` API, iodine will support you - but be aware that you will need to implement your own reactor and thread pool for any sockets you hijack, as well as a socket buffer for non-blocking `write` operations (why do that when you can write a protocol object and have the main reactor manage the socket?).
192
251
 
193
252
  ### Performance oriented design - but safety first
194
253
 
@@ -225,13 +284,13 @@ The slower your application code, the more threads you will need to keep the ser
225
284
 
226
285
  ### How does it compare to other servers?
227
286
 
228
- Personally, after looking around, the only comparable servers are Puma and Passenger, which Iodine significantly outperformed on my tests (I didn't test Passenger's enterprise version).
287
+ Personally, after looking around, the only comparable servers are Puma and Passenger, which iodine significantly outperformed on my tests (I didn't test Passenger's enterprise version).
229
288
 
230
289
  Since the HTTP and Websocket parsers are written in C (with no RegExp), they're fairly fast.
231
290
 
232
- Also, Iodine's core and parsers are running outside of Ruby's global lock, meaning that they enjoy true concurrency before entering the Ruby layer (your application) - this offers Iodine a big advantage over other Ruby servers.
291
+ Also, iodine's core and parsers are running outside of Ruby's global lock, meaning that they enjoy true concurrency before entering the Ruby layer (your application) - this offers iodine a big advantage over other Ruby servers.
233
292
 
234
- Another assumption Iodine makes is that it is behind a load balancer / proxy (which is the normal way Ruby applications are deployed) - this allows Iodine to disregard header validity checks (we're not checking for invalid characters) and focus it's resources on other security and performance concerns.
293
+ Another assumption iodine makes is that it is behind a load balancer / proxy (which is the normal way Ruby applications are deployed) - this allows iodine to disregard header validity checks (we're not checking for invalid characters) and focus it's resources on other security and performance concerns.
235
294
 
236
295
  I recommend benchmarking the performance for yourself using `wrk` or `ab`:
237
296
 
@@ -254,7 +313,7 @@ end
254
313
  run App
255
314
  ```
256
315
 
257
- Then start comparing servers. Here are the settings I used to compare Iodine and Puma (4 processes, 16 threads):
316
+ Then start comparing servers. Here are the settings I used to compare iodine and Puma (4 processes, 16 threads):
258
317
 
259
318
  ```bash
260
319
  $ RACK_ENV=production iodine -p 3000 -t 16 -w 4
@@ -264,11 +323,11 @@ $ RACK_ENV=production puma -p 3000 -t 16 -w 4
264
323
  ```
265
324
 
266
325
 
267
- When benchmarking with `wrk`, Iodine performed significantly better, (~62K req/sec vs. ~44K req/sec) while keeping a lower memory foot print (~60Mb vs. ~111Mb).
326
+ When benchmarking with `wrk`, iodine performed significantly better, (~62K req/sec vs. ~44K req/sec) while keeping a lower memory foot print (~60Mb vs. ~111Mb).
268
327
 
269
- When benchmarking with `ab`, I got different results, where Iodine still performed significantly better, (~72K req/sec vs. ~36K req/sec and ~61Mb vs. ~81.6Mb). I suspect the difference between the two benchmarks has to do with system calls to `write`, but I have no real proof.
328
+ When benchmarking with `ab`, I got different results, where iodine still performed significantly better, (~72K req/sec vs. ~36K req/sec and ~61Mb vs. ~81.6Mb). I suspect the difference between the two benchmarks has to do with system calls to `write`, but I have no real proof.
270
329
 
271
- Remember to compare the memory footprint after running some requests - it's not just speed that C is helping with, it's also memory management and object pooling (i.e., Iodine uses a buffer packet pool management).
330
+ Remember to compare the memory footprint after running some requests - it's not just speed that C is helping with, it's also memory management and object pooling (i.e., iodine uses a buffer packet pool management).
272
331
 
273
332
  ## Can I try before I buy?
274
333
 
@@ -282,7 +341,7 @@ $ gem install iodine
282
341
 
283
342
  If building the native C extension fails, please note that some Ruby installations, such as on Ubuntu, require that you separately install the development headers (`ruby.h` and friends). I have no idea why they do that, as you will need the development headers for any native gems you want to install - so hurry up and get them.
284
343
 
285
- If you have the development headers but still can't compile the Iodine extension, [open an issue](https://github.com/boazsegev/iodine/issues) with any messages you're getting and I'll be happy to look into it.
344
+ If you have the development headers but still can't compile the iodine extension, [open an issue](https://github.com/boazsegev/iodine/issues) with any messages you're getting and I'll be happy to look into it.
286
345
 
287
346
  ## Mr. Sandman, write me a server
288
347
 
@@ -330,7 +389,7 @@ But me, I prefer to make sure my development software runs the exact same code a
330
389
 
331
390
  Also, I don't really understand all the minute details of EventMachine's API, it kept crashing my system every time I reached 1K-2K active connections... I'm sure I just don't know how to use EventMachine, but that's just that.
332
391
 
333
- Besides, you're here - why not take Iodine out for a spin and see for yourself?
392
+ Besides, you're here - why not take iodine out for a spin and see for yourself?
334
393
 
335
394
  ## Can I contribute?
336
395
 
@@ -364,7 +423,7 @@ Here's a few things you can use from this project and they seem to be handy to h
364
423
 
365
424
  This one is a simple binary tree with a Ruby GC callback. Remember to initialize the Registry (`Registry.init(owner)`) so it's "owned" by some Ruby-land object, this allows it to bridge the two worlds for the GC's mark and sweep.
366
425
 
367
- I'm attaching it to one of Iodine's library classes, just in-case someone adopts my code and decides the registry should be owned by the global Object class.
426
+ I'm attaching it to one of iodine's library classes, just in-case someone adopts my code and decides the registry should be owned by the global Object class.
368
427
 
369
428
  * I was using a POSIX thread pool library ([`libasync.h`](https://github.com/boazsegev/facil.io/blob/master/lib/libasync.c)) until I realized how many issues Ruby has with non-Ruby threads... So now there's a Ruby-thread port for this library at ([`rb-libasync.h`](https://github.com/boazsegev/iodine/blob/master/ext/iodine/rb-libasync.h)).
370
429
 
@@ -8,14 +8,13 @@
8
8
  # REDIS_URL=redis://localhost:6379/0 iodine -t 1 -p 3030 redis.ru
9
9
  #
10
10
  require 'uri'
11
- # initialize the Redis engine for each Iodine process by using `Iodine.run`
11
+ # initialize the Redis engine for each Iodine process.
12
12
  if ENV["REDIS_URL"]
13
13
  uri = URI(ENV["REDIS_URL"])
14
14
  Iodine.default_pubsub = Iodine::PubSub::RedisEngine.new(uri.host, uri.port, 0, uri.password)
15
15
  else
16
- puts "* No Redis! pub/sub is limited to the process cluster."
16
+ puts "* No Redis, it's okay, pub/sub will still run on the whole process cluster."
17
17
  end
18
- puts "The default Pub/Sub engine is:", Iodine.default_pubsub
19
18
 
20
19
  # A simple router - Checks for Websocket Upgrade and answers HTTP.
21
20
  module MyHTTPRouter
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Boaz Segev']
10
10
  spec.email = ['bo@plezi.io']
11
11
 
12
- spec.summary = ' Iodine - HTTP / Websocket Server & EventMachine alternative for Ruby MRI - a kqueue/epoll C extension.'
13
- spec.description = ' Iodine - HTTP / Websocket Server & EventMachine alternative for Ruby MRI - a kqueue/epoll C extension.'
12
+ spec.summary = 'iodine - HTTP / Websocket Server with Pub/Sub support, optimized for Ruby MRI on Linux / BSD'
13
+ spec.description = 'iodine - HTTP / Websocket Server with Pub/Sub support, optimized for Ruby MRI on Linux / BSD'
14
14
  spec.homepage = 'https://github.com/boazsegev/iodine'
15
15
  spec.license = 'MIT'
16
16
 
@@ -32,7 +32,6 @@ Gem::Specification.new do |spec|
32
32
  spec.required_ruby_version = '>= 2.2.2' # Because earlier versions had been discontinued
33
33
 
34
34
  spec.add_dependency 'rack'
35
- spec.add_dependency 'rake-compiler', '>= 1'
36
35
 
37
36
  spec.requirements << 'A Unix based system: Linux / macOS / BSD.'
38
37
  spec.requirements << 'An updated C compiler.'
@@ -42,6 +41,7 @@ Gem::Specification.new do |spec|
42
41
  spec.add_development_dependency 'bundler', '>= 1.10'
43
42
  spec.add_development_dependency 'rake', '~> 12.0'
44
43
  spec.add_development_dependency 'minitest', '>=5'
44
+ spec.add_development_dependency 'rake-compiler', '>= 1'
45
45
 
46
46
  # spec.post_install_message = "** WARNING!\n" \
47
47
  # "Iodine 0.2.0 is NOT an upgrade - it's a total rewrite, it's written in C specifically for Ruby MRI.\n\n" \
@@ -152,16 +152,18 @@ module Iodine
152
152
  # Use {warmup} when either {processes} or {threads} are set to more then 1.
153
153
  def self.warmup app
154
154
  # load anything marked with `autoload`, since autoload isn't thread safe nor fork friendly.
155
- Module.constants.each do |n|
156
- begin
157
- Object.const_get(n)
158
- rescue Exception => _e
155
+ Iodine.run do
156
+ Module.constants.each do |n|
157
+ begin
158
+ Object.const_get(n)
159
+ rescue Exception => _e
160
+ end
159
161
  end
160
- end
161
- ::Rack::Builder.new(app) do |r|
162
- r.warmup do |a|
163
- client = ::Rack::MockRequest.new(a)
164
- client.get('/')
162
+ ::Rack::Builder.new(app) do |r|
163
+ r.warmup do |a|
164
+ client = ::Rack::MockRequest.new(a)
165
+ client.get('/')
166
+ end
165
167
  end
166
168
  end
167
169
  end
@@ -11,27 +11,32 @@ module Iodine
11
11
  #
12
12
  # require 'iodine'
13
13
  # require 'rack'
14
+ # # a String in need of decoding
14
15
  # s = '%E3%83%AB%E3%83%93%E3%82%A4%E3%82%B9%E3%81%A8'
15
16
  # Benchmark.bm do |bm|
16
17
  # # Pre-Patch
17
- # bm.report("Rack") {1_000_000.times { Rack::Utils.unescape s } }
18
- #
18
+ # bm.report(" Rack.unescape") {1_000_000.times { Rack::Utils.unescape s } }
19
+ # bm.report(" Rack.rfc2822") {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
20
+ # bm.report(" Rack.rfc2109") {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
19
21
  # # Perform Patch
20
- # Rack::Utils.class_eval do
21
- # Iodine::Base::MonkeyPatch::RackUtils.methods(false).each do |m|
22
- # define_singleton_method(m,
23
- # Iodine::Base::MonkeyPatch::RackUtils.instance_method(m) )
24
- # end
25
- # end
26
- #
22
+ # Iodine.patch_rack
23
+ # puts " --- Monkey Patching Rack ---"
27
24
  # # Post Patch
28
- # bm.report("Patched") {1_000_000.times { Rack::Utils.unescape s } }
25
+ # bm.report("Patched.unescape") {1_000_000.times { Rack::Utils.unescape s } }
26
+ # bm.report(" Patched.rfc2822") {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
27
+ # bm.report(" Patched.rfc2109") {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
29
28
  # end && nil
30
29
  #
31
30
  # Results:
32
31
  # user system total real
33
- # Rack 8.620000 0.020000 8.640000 ( 8.636676)
34
- # Patched 0.320000 0.000000 0.320000 ( 0.322377)
32
+ # Rack.unescape 8.660000 0.010000 8.670000 ( 8.687807)
33
+ # Rack.rfc2822 3.730000 0.000000 3.730000 ( 3.727732)
34
+ # Rack.rfc2109 3.020000 0.010000 3.030000 ( 3.031940)
35
+ # --- Monkey Patching Rack ---
36
+ # Patched.unescape 0.340000 0.000000 0.340000 ( 0.341506)
37
+ # Patched.rfc2822 0.740000 0.000000 0.740000 ( 0.737796)
38
+ # Patched.rfc2109 0.690000 0.010000 0.700000 ( 0.700155)
39
+ #
35
40
  module RackUtils
36
41
  end
37
42
  end
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.4.0'.freeze
2
+ VERSION = '0.4.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-21 00:00:00.000000000 Z
11
+ date: 2017-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: rake-compiler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '1'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '1'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: bundler
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,8 +66,22 @@ dependencies:
80
66
  - - ">="
81
67
  - !ruby/object:Gem::Version
82
68
  version: '5'
83
- description: " Iodine - HTTP / Websocket Server & EventMachine alternative for Ruby
84
- MRI - a kqueue/epoll C extension."
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake-compiler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '1'
83
+ description: iodine - HTTP / Websocket Server with Pub/Sub support, optimized for
84
+ Ruby MRI on Linux / BSD
85
85
  email:
86
86
  - bo@plezi.io
87
87
  executables:
@@ -240,6 +240,6 @@ rubyforge_project:
240
240
  rubygems_version: 2.6.11
241
241
  signing_key:
242
242
  specification_version: 4
243
- summary: Iodine - HTTP / Websocket Server & EventMachine alternative for Ruby MRI
244
- - a kqueue/epoll C extension.
243
+ summary: iodine - HTTP / Websocket Server with Pub/Sub support, optimized for Ruby
244
+ MRI on Linux / BSD
245
245
  test_files: []