rainbows.git  about / heads / tags
Unicorn for sleepy apps and slow clients
blob 8586a0b8b7bf495d717386dfc6d0f2a535443135 10346 bytes (raw)
$ git show HEAD:Documentation/comparison.haml	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
 
%h1 Rainbows! at a glance
%p
  Confused by all the options we give you?  So are we!  Here's some tables
  to help keep your head straight.  Remember, engineering is all about
  trade-offs.
%h2 core features and compatibility
%br
%table.comp
  %tr.comp_header
    %th.mod module
    %th.tee rack.input streaming
    %th.r18 Ruby 1.8
    %th.r19 Ruby 1.9
    %th.rbx Rubinius
    %th.slow slow clients
  %tr.comp_base
    %td.mod Unicorn/Base
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow No
  %tr.comp_row
    %td.mod Revactor
    %td.tee Yes
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod ThreadPool
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod Coolio
    %td.tee No
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod ThreadSpawn
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod EventMachine
    %td.tee No
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod CoolioThreadSpawn
    %td.tee No
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod FiberSpawn
    %td.tee Yes
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod FiberPool
    %td.tee Yes
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_base
    %td.mod ActorSpawn
    %td.tee Yes
    %td.r18 Not yet
    %td.r19 No
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_base
    %td.mod NeverBlock
    %td.tee No
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod CoolioThreadPool
    %td.tee No
    %td.r18 Yes
    %td.r19 No
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod CoolioFiberSpawn
    %td.tee Yes
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod WriterThreadPool
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow no
  %tr.comp_row
    %td.mod WriterThreadSpawn
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow no
  %tr.comp_row
    %td.mod Epoll
    %td.tee no
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod XEpoll
    %td.tee no
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod XEpollThreadSpawn
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod XEpollThreadPool
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
%ul
  %li
    Cool.io should also work with Rubinius (though we haven't had time to test).
  %li
    CoolioThread* and CoolioThread* requires Ruby 1.9 reasonable performance
  %li
    rack.input streaming is what makes
    %a(href="http://yhbt.net/upr/") upload progress,
    and BOSH possible
  %li
    rack.input streaming is NOT compatible with current versions of nginx
    or any proxy that fully buffers request bodies before proxying.
    Keep in mind request body buffering in nginx is a good thing in all
    other cases where rack.input streaming is not needed.

%h2 application requirements
%br
%table.comp
  %tr.comp_header
    %th.mod module
    %th.slowio slow I/O (backend, not client)
    %th.thr thread safety
    %th.reent single thread reentrant
  %tr.comp_base
    %td.mod Unicorn/Base
    %td.slowio avoid
    %td.thr No
    %td.reent No
  %tr.comp_row
    %td.mod Revactor
    %td.slowio
      %a(href="http://coolio.github.com/")Coolio,
      %a(href="http://revactor.org/")Revactor,
      %b
        not
      %a(href="Rainbows/Fiber/IO.html")Fiber::IO
    %td.thr No
    %td.reent Yes
  %tr.comp_row
    %td.mod ThreadPool
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent No
  %tr.comp_row
    %td.mod Coolio
    %td.slowio
      %a(href="http://coolio.github.com/") Coolio
    %td.thr No
    %td.reent No
  %tr.comp_row
    %td.mod ThreadSpawn
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent No
  %tr.comp_row
    %td.mod EventMachine
    %td.slowio
      %a(href="http://rubyeventmachine.com") EventMachine
    %td.thr No
    %td.reent No
  %tr.comp_row
    %td.mod CoolioThreadSpawn
    %td.slowio
      thread-safe Ruby,
      %a(href="http://coolio.github.com/") Coolio
    %td.thr Yes
    %td.reent No
  %tr.comp_row
    %td.mod FiberSpawn
    %td.slowio
      %a(href="Rainbows/Fiber/IO.html") Rainbows::Fiber::IO
    %td.thr No
    %td.reent Yes
  %tr.comp_row
    %td.mod FiberPool
    %td.slowio
      %a(href="Rainbows/Fiber/IO.html") Rainbows::Fiber::IO
    %td.thr No
    %td.reent Yes
  %tr.comp_base
    %td.mod ActorSpawn
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent Yes
  %tr.comp_base
    %td.mod NeverBlock
    %td.slowio
      %a(href="http://www.espace.com.eg/neverblock") NeverBlock,
      %a(href="http://rubyeventmachine.com") EventMachine
    %td.thr No
    %td.reent Yes
  %tr.comp_row
    %td.mod CoolioThreadPool
    %td.slowio
      thread-safe Ruby,
      %a(href="http://coolio.github.com/") Coolio
    %td.thr Yes
    %td.reent No
  %tr.comp_row
    %td.mod CoolioFiberSpawn
    %td.slowio
      %a(href="Rainbows/Fiber/IO.html") Rainbows::Fiber::IO
    %td.thr No
    %td.reent Yes
  %tr.comp_base
    %td.mod WriterThreadPool
    %td.slowio avoid
    %td.thr Maybe
    %td.reent Maybe
  %tr.comp_base
    %td.mod WriterThreadSpawn
    %td.slowio avoid
    %td.thr Maybe
    %td.reent Maybe
  %tr.comp_base
    %td.mod Epoll
    %td.slowio No
    %td.thr No
    %td.reent No
  %tr.comp_base
    %td.mod XEpoll
    %td.slowio No
    %td.thr No
    %td.reent No
  %tr.comp_base
    %td.mod XEpollThreadSpawn
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent No
  %tr.comp_base
    %td.mod XEpollThreadPool
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent No
%ul
  %li
    Requirements for single thread reentrancy are loose in that there is
    no risk of race conditions and potentially mutually exclusive to
    thread-safety.  In the case where a Fiber yields while holding a
    resource and another Fiber attempting to acquire it may raise
    an error or worse, deadlock the entire process.
  %li
    Slow I/O means anything that can block/stall on sockets including
    3rd-party APIs (OpenID providers included) or slow database queries.
    Properly run Memcached (within the same LAN) is fast and not a blocker.
    Slow I/O on POSIX filesystems only includes a few operations, namely
    on UNIX domain sockets and named pipes.  Nearly all other operations
    on POSIX filesystems can be considered "fast", or at least
    uninterruptible.
  %li
    WriterThread{Pool,Spawn} will require thread safety if your response
    body is dynamically generated during the body#each call.

%h2 middlewares and frameworks
%br

%table.comp
  %tr.comp_header
    %th.mod model
    %th.devfd
      %a(href="Rainbows/DevFdResponse.html") DevFdResponse
    %th.app_pool
      %a(href="Rainbows/AppPool.html") AppPool
    %th.lock
      %a(href="http://rdoc.info/gems/rack/Rack/Lock") Rack::Lock
    %th.async async
  %tr.comp_row
    %td.mod Unicorn/Base
    %td.devfd no-op
    %td.app_pool no-op
    %td.lock no-op
    %td.async lots of RAM :P
  %tr.comp_row
    %td.mod Revactor
    %td.devfd no-op
    %td.app_pool Yes
    %td.lock No!
    %td.async Revactor itself
  %tr.comp_row
    %td.mod ThreadPool
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod Coolio
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async DevFdResponse
  %tr.comp_row
    %td.mod ThreadSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod EventMachine
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async async_sinatra, Cramp, rack-fiber_pool
  %tr.comp_row
    %td.mod CoolioThreadSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Dumb
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod FiberSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock No!
    %td.async Rainbows::Fiber::IO, Rainbows.sleep
  %tr.comp_row
    %td.mod FiberPool
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock No!
    %td.async Rainbows::Fiber::IO, Rainbows.sleep
  %tr.comp_row
    %td.mod ActorSpawn
    %td.devfd no-op
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod NeverBlock
    %td.devfd Yes
    %td.app_pool Yes*
    %td.lock Yes*
    %td.async NeverBlock, async_sinatra
  %tr.comp_row
    %td.mod CoolioThreadPool
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Dumb
    %td.async Coolio, thread-safe Ruby
  %tr.comp_row
    %td.mod CoolioFiberSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock No!
    %td.async Coolio, Rainbows::Fiber::IO, Rainbows.sleep
  %tr.comp_row
    %td.mod WriterThreadPool
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async thread-safe Ruby in response body only
  %tr.comp_row
    %td.mod WriterThreadSpawn
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async thread-safe Ruby in response body only
  %tr.comp_row
    %td.mod Epoll
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async DevFdResponse
  %tr.comp_row
    %td.mod XEpoll
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async DevFdResponse
  %tr.comp_row
    %td.mod XEpollThreadPool
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod XEpollThreadSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
%ul
  %li
    "No!" means it's fundamentally incompatible, use an
    %a(href="Rainbows/AppPool.html") AppPool
    %b :size
    of one instead.
  %li
    NeverBlock also supports a :pool_size option which is one less
    layer of complexity than using AppPool.
  %li
    NeverBlock can neuter the Mutex class so Rack::Lock effectively
    becomes a no-op with:
    %br
    %code require "never_block/frameworks/rails"
    (before Rails is loaded)
  %li
    Everything that's DevFdResponse-compatible can use it for passing
    async responses through

git clone https://yhbt.net/rainbows.git