mega-max-tool 0.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.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/mega-max-tool.gemspec +12 -0
  3. data/unicorn-6.1.0/Application_Timeouts +77 -0
  4. data/unicorn-6.1.0/CONTRIBUTORS +39 -0
  5. data/unicorn-6.1.0/COPYING +674 -0
  6. data/unicorn-6.1.0/DESIGN +95 -0
  7. data/unicorn-6.1.0/Documentation/unicorn.1 +222 -0
  8. data/unicorn-6.1.0/Documentation/unicorn_rails.1 +207 -0
  9. data/unicorn-6.1.0/FAQ +70 -0
  10. data/unicorn-6.1.0/GIT-VERSION-FILE +1 -0
  11. data/unicorn-6.1.0/GIT-VERSION-GEN +39 -0
  12. data/unicorn-6.1.0/GNUmakefile +313 -0
  13. data/unicorn-6.1.0/HACKING +112 -0
  14. data/unicorn-6.1.0/ISSUES +97 -0
  15. data/unicorn-6.1.0/KNOWN_ISSUES +79 -0
  16. data/unicorn-6.1.0/LATEST +24 -0
  17. data/unicorn-6.1.0/LICENSE +67 -0
  18. data/unicorn-6.1.0/Links +58 -0
  19. data/unicorn-6.1.0/NEWS +2890 -0
  20. data/unicorn-6.1.0/PHILOSOPHY +139 -0
  21. data/unicorn-6.1.0/README +151 -0
  22. data/unicorn-6.1.0/Rakefile +16 -0
  23. data/unicorn-6.1.0/SIGNALS +123 -0
  24. data/unicorn-6.1.0/Sandbox +104 -0
  25. data/unicorn-6.1.0/TODO +3 -0
  26. data/unicorn-6.1.0/TUNING +119 -0
  27. data/unicorn-6.1.0/archive/slrnpull.conf +4 -0
  28. data/unicorn-6.1.0/bin/unicorn +128 -0
  29. data/unicorn-6.1.0/bin/unicorn_rails +209 -0
  30. data/unicorn-6.1.0/examples/big_app_gc.rb +2 -0
  31. data/unicorn-6.1.0/examples/echo.ru +27 -0
  32. data/unicorn-6.1.0/examples/init.sh +102 -0
  33. data/unicorn-6.1.0/examples/logger_mp_safe.rb +25 -0
  34. data/unicorn-6.1.0/examples/logrotate.conf +44 -0
  35. data/unicorn-6.1.0/examples/nginx.conf +156 -0
  36. data/unicorn-6.1.0/examples/unicorn.conf.minimal.rb +13 -0
  37. data/unicorn-6.1.0/examples/unicorn.conf.rb +110 -0
  38. data/unicorn-6.1.0/examples/unicorn.socket +11 -0
  39. data/unicorn-6.1.0/examples/unicorn@.service +40 -0
  40. data/unicorn-6.1.0/ext/unicorn_http/CFLAGS +13 -0
  41. data/unicorn-6.1.0/ext/unicorn_http/c_util.h +116 -0
  42. data/unicorn-6.1.0/ext/unicorn_http/common_field_optimization.h +128 -0
  43. data/unicorn-6.1.0/ext/unicorn_http/epollexclusive.h +124 -0
  44. data/unicorn-6.1.0/ext/unicorn_http/ext_help.h +38 -0
  45. data/unicorn-6.1.0/ext/unicorn_http/extconf.rb +37 -0
  46. data/unicorn-6.1.0/ext/unicorn_http/global_variables.h +97 -0
  47. data/unicorn-6.1.0/ext/unicorn_http/httpdate.c +79 -0
  48. data/unicorn-6.1.0/ext/unicorn_http/unicorn_http.c +4319 -0
  49. data/unicorn-6.1.0/ext/unicorn_http/unicorn_http.rl +1025 -0
  50. data/unicorn-6.1.0/ext/unicorn_http/unicorn_http_common.rl +76 -0
  51. data/unicorn-6.1.0/lib/unicorn/app/old_rails/static.rb +59 -0
  52. data/unicorn-6.1.0/lib/unicorn/app/old_rails.rb +35 -0
  53. data/unicorn-6.1.0/lib/unicorn/cgi_wrapper.rb +147 -0
  54. data/unicorn-6.1.0/lib/unicorn/configurator.rb +743 -0
  55. data/unicorn-6.1.0/lib/unicorn/const.rb +21 -0
  56. data/unicorn-6.1.0/lib/unicorn/http_request.rb +201 -0
  57. data/unicorn-6.1.0/lib/unicorn/http_response.rb +61 -0
  58. data/unicorn-6.1.0/lib/unicorn/http_server.rb +893 -0
  59. data/unicorn-6.1.0/lib/unicorn/launcher.rb +62 -0
  60. data/unicorn-6.1.0/lib/unicorn/oob_gc.rb +81 -0
  61. data/unicorn-6.1.0/lib/unicorn/preread_input.rb +33 -0
  62. data/unicorn-6.1.0/lib/unicorn/select_waiter.rb +6 -0
  63. data/unicorn-6.1.0/lib/unicorn/socket_helper.rb +211 -0
  64. data/unicorn-6.1.0/lib/unicorn/stream_input.rb +147 -0
  65. data/unicorn-6.1.0/lib/unicorn/tee_input.rb +131 -0
  66. data/unicorn-6.1.0/lib/unicorn/tmpio.rb +33 -0
  67. data/unicorn-6.1.0/lib/unicorn/util.rb +90 -0
  68. data/unicorn-6.1.0/lib/unicorn/version.rb +1 -0
  69. data/unicorn-6.1.0/lib/unicorn/worker.rb +165 -0
  70. data/unicorn-6.1.0/lib/unicorn.rb +138 -0
  71. data/unicorn-6.1.0/man/man1/unicorn.1 +222 -0
  72. data/unicorn-6.1.0/man/man1/unicorn_rails.1 +207 -0
  73. data/unicorn-6.1.0/setup.rb +1586 -0
  74. data/unicorn-6.1.0/t/GNUmakefile +5 -0
  75. data/unicorn-6.1.0/t/README +42 -0
  76. data/unicorn-6.1.0/t/bin/content-md5-put +36 -0
  77. data/unicorn-6.1.0/t/bin/sha1sum.rb +17 -0
  78. data/unicorn-6.1.0/t/bin/unused_listen +40 -0
  79. data/unicorn-6.1.0/t/broken-app.ru +12 -0
  80. data/unicorn-6.1.0/t/detach.ru +11 -0
  81. data/unicorn-6.1.0/t/env.ru +3 -0
  82. data/unicorn-6.1.0/t/fails-rack-lint.ru +5 -0
  83. data/unicorn-6.1.0/t/heartbeat-timeout.ru +12 -0
  84. data/unicorn-6.1.0/t/listener_names.ru +4 -0
  85. data/unicorn-6.1.0/t/my-tap-lib.sh +201 -0
  86. data/unicorn-6.1.0/t/oob_gc.ru +20 -0
  87. data/unicorn-6.1.0/t/oob_gc_path.ru +20 -0
  88. data/unicorn-6.1.0/t/pid.ru +3 -0
  89. data/unicorn-6.1.0/t/preread_input.ru +17 -0
  90. data/unicorn-6.1.0/t/rack-input-tests.ru +21 -0
  91. data/unicorn-6.1.0/t/t0000-http-basic.sh +50 -0
  92. data/unicorn-6.1.0/t/t0001-reload-bad-config.sh +53 -0
  93. data/unicorn-6.1.0/t/t0002-config-conflict.sh +49 -0
  94. data/unicorn-6.1.0/t/t0002-parser-error.sh +94 -0
  95. data/unicorn-6.1.0/t/t0003-working_directory.sh +51 -0
  96. data/unicorn-6.1.0/t/t0004-heartbeat-timeout.sh +69 -0
  97. data/unicorn-6.1.0/t/t0004-working_directory_broken.sh +24 -0
  98. data/unicorn-6.1.0/t/t0005-working_directory_app.rb.sh +40 -0
  99. data/unicorn-6.1.0/t/t0006-reopen-logs.sh +83 -0
  100. data/unicorn-6.1.0/t/t0006.ru +13 -0
  101. data/unicorn-6.1.0/t/t0007-working_directory_no_embed_cli.sh +44 -0
  102. data/unicorn-6.1.0/t/t0008-back_out_of_upgrade.sh +110 -0
  103. data/unicorn-6.1.0/t/t0009-broken-app.sh +56 -0
  104. data/unicorn-6.1.0/t/t0009-winch_ttin.sh +59 -0
  105. data/unicorn-6.1.0/t/t0010-reap-logging.sh +55 -0
  106. data/unicorn-6.1.0/t/t0011-active-unix-socket.sh +79 -0
  107. data/unicorn-6.1.0/t/t0012-reload-empty-config.sh +86 -0
  108. data/unicorn-6.1.0/t/t0013-rewindable-input-false.sh +24 -0
  109. data/unicorn-6.1.0/t/t0013.ru +12 -0
  110. data/unicorn-6.1.0/t/t0014-rewindable-input-true.sh +24 -0
  111. data/unicorn-6.1.0/t/t0014.ru +12 -0
  112. data/unicorn-6.1.0/t/t0015-configurator-internals.sh +25 -0
  113. data/unicorn-6.1.0/t/t0018-write-on-close.sh +23 -0
  114. data/unicorn-6.1.0/t/t0019-max_header_len.sh +49 -0
  115. data/unicorn-6.1.0/t/t0020-at_exit-handler.sh +49 -0
  116. data/unicorn-6.1.0/t/t0021-process_detach.sh +29 -0
  117. data/unicorn-6.1.0/t/t0022-listener_names-preload_app.sh +32 -0
  118. data/unicorn-6.1.0/t/t0100-rack-input-tests.sh +124 -0
  119. data/unicorn-6.1.0/t/t0116-client_body_buffer_size.sh +80 -0
  120. data/unicorn-6.1.0/t/t0116.ru +16 -0
  121. data/unicorn-6.1.0/t/t0300-no-default-middleware.sh +20 -0
  122. data/unicorn-6.1.0/t/t0301-no-default-middleware-ignored-in-config.sh +25 -0
  123. data/unicorn-6.1.0/t/t0301.ru +13 -0
  124. data/unicorn-6.1.0/t/t9000-preread-input.sh +48 -0
  125. data/unicorn-6.1.0/t/t9001-oob_gc.sh +47 -0
  126. data/unicorn-6.1.0/t/t9002-oob_gc-path.sh +75 -0
  127. data/unicorn-6.1.0/t/test-lib.sh +129 -0
  128. data/unicorn-6.1.0/t/write-on-close.ru +11 -0
  129. data/unicorn-6.1.0/test/aggregate.rb +15 -0
  130. data/unicorn-6.1.0/test/benchmark/README +60 -0
  131. data/unicorn-6.1.0/test/benchmark/dd.ru +18 -0
  132. data/unicorn-6.1.0/test/benchmark/ddstream.ru +50 -0
  133. data/unicorn-6.1.0/test/benchmark/readinput.ru +40 -0
  134. data/unicorn-6.1.0/test/benchmark/stack.ru +8 -0
  135. data/unicorn-6.1.0/test/benchmark/uconnect.perl +66 -0
  136. data/unicorn-6.1.0/test/exec/README +5 -0
  137. data/unicorn-6.1.0/test/exec/test_exec.rb +1101 -0
  138. data/unicorn-6.1.0/test/test_helper.rb +306 -0
  139. data/unicorn-6.1.0/test/unit/test_ccc.rb +91 -0
  140. data/unicorn-6.1.0/test/unit/test_configurator.rb +175 -0
  141. data/unicorn-6.1.0/test/unit/test_droplet.rb +28 -0
  142. data/unicorn-6.1.0/test/unit/test_http_parser.rb +884 -0
  143. data/unicorn-6.1.0/test/unit/test_http_parser_ng.rb +714 -0
  144. data/unicorn-6.1.0/test/unit/test_request.rb +182 -0
  145. data/unicorn-6.1.0/test/unit/test_response.rb +111 -0
  146. data/unicorn-6.1.0/test/unit/test_server.rb +342 -0
  147. data/unicorn-6.1.0/test/unit/test_signals.rb +188 -0
  148. data/unicorn-6.1.0/test/unit/test_socket_helper.rb +201 -0
  149. data/unicorn-6.1.0/test/unit/test_stream_input.rb +203 -0
  150. data/unicorn-6.1.0/test/unit/test_tee_input.rb +304 -0
  151. data/unicorn-6.1.0/test/unit/test_upload.rb +301 -0
  152. data/unicorn-6.1.0/test/unit/test_util.rb +131 -0
  153. data/unicorn-6.1.0/test/unit/test_waiter.rb +34 -0
  154. data/unicorn-6.1.0/unicorn.gemspec +49 -0
  155. data/unicorn-6.1.0/unicorn_1 +1 -0
  156. data/unicorn-6.1.0/unicorn_rails_1 +1 -0
  157. metadata +196 -0
@@ -0,0 +1,25 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 3 "-N / --no-default-middleware option not supported in config.ru"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ RACK_ENV=development unicorn -D -c $unicorn_config t0301.ru
8
+ unicorn_wait_start
9
+ }
10
+
11
+ t_begin "check switches parsed as expected and -N ignored for Rack::Lint" && {
12
+ debug=false
13
+ lint=
14
+ eval "$(curl -sf http://$listen/vars)"
15
+ test x"$debug" = xtrue
16
+ test x"$lint" != x
17
+ test -f "$lint"
18
+ }
19
+
20
+ t_begin "killing succeeds" && {
21
+ kill $unicorn_pid
22
+ check_stderr
23
+ }
24
+
25
+ t_done
@@ -0,0 +1,13 @@
1
+ #\-N --debug
2
+ run(lambda do |env|
3
+ case env['PATH_INFO']
4
+ when '/vars'
5
+ b = "debug=#{$DEBUG.inspect}\n" \
6
+ "lint=#{caller.grep(%r{rack/lint\.rb})[0].split(':')[0]}\n"
7
+ end
8
+ h = {
9
+ 'Content-Length' => b.size.to_s,
10
+ 'Content-Type' => 'text/plain',
11
+ }
12
+ [ 200, h, [ b ] ]
13
+ end)
@@ -0,0 +1,48 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 9 "PrereadInput middleware tests"
4
+
5
+ t_begin "setup and start" && {
6
+ random_blob_sha1=$(rsha1 < random_blob)
7
+ unicorn_setup
8
+ unicorn -D -c $unicorn_config preread_input.ru
9
+ unicorn_wait_start
10
+ }
11
+
12
+ t_begin "single identity request" && {
13
+ curl -sSf -T random_blob http://$listen/ > $tmp
14
+ }
15
+
16
+ t_begin "sha1 matches" && {
17
+ test x"$(cat $tmp)" = x"$random_blob_sha1"
18
+ }
19
+
20
+ t_begin "single chunked request" && {
21
+ curl -sSf -T- < random_blob http://$listen/ > $tmp
22
+ }
23
+
24
+ t_begin "sha1 matches" && {
25
+ test x"$(cat $tmp)" = x"$random_blob_sha1"
26
+ }
27
+
28
+ t_begin "app only dispatched twice" && {
29
+ test 2 -eq "$(grep 'app dispatch:' < $r_err | count_lines )"
30
+ }
31
+
32
+ t_begin "aborted chunked request" && {
33
+ rm -f $tmp
34
+ curl -sSf -T- < $fifo http://$listen/ > $tmp &
35
+ curl_pid=$!
36
+ kill -9 $curl_pid
37
+ wait
38
+ }
39
+
40
+ t_begin "app only dispatched twice" && {
41
+ test 2 -eq "$(grep 'app dispatch:' < $r_err | count_lines )"
42
+ }
43
+
44
+ t_begin "killing succeeds" && {
45
+ kill -QUIT $unicorn_pid
46
+ }
47
+
48
+ t_done
@@ -0,0 +1,47 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 9 "OobGC test"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ unicorn -D -c $unicorn_config oob_gc.ru
8
+ unicorn_wait_start
9
+ }
10
+
11
+ t_begin "test default interval (4 requests)" && {
12
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
13
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
14
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
15
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
16
+ }
17
+
18
+ t_begin "GC starting-request returns immediately" && {
19
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
20
+ }
21
+
22
+ t_begin "GC is started after 5 requests" && {
23
+ test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp)
24
+ }
25
+
26
+ t_begin "reset GC" && {
27
+ test xfalse = x$(curl -vsSf -X POST http://$listen/gc_reset 2>> $tmp)
28
+ }
29
+
30
+ t_begin "test default interval again (3 requests)" && {
31
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
32
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
33
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
34
+ }
35
+
36
+ t_begin "GC is started after 5 requests" && {
37
+ test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp)
38
+ }
39
+
40
+ t_begin "killing succeeds" && {
41
+ kill -QUIT $unicorn_pid
42
+ }
43
+
44
+ t_begin "check_stderr" && check_stderr
45
+ dbgcat r_err
46
+
47
+ t_done
@@ -0,0 +1,75 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 12 "OobGC test with limited path"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ unicorn -D -c $unicorn_config oob_gc_path.ru
8
+ unicorn_wait_start
9
+ }
10
+
11
+ t_begin "test default is noop" && {
12
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
13
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
14
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
15
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
16
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
17
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
18
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
19
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
20
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
21
+ }
22
+
23
+ t_begin "4 bad requests to bump counter" && {
24
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
25
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
26
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
27
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
28
+ }
29
+
30
+ t_begin "GC-starting request returns immediately" && {
31
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
32
+ }
33
+
34
+ t_begin "GC was started after 5 requests" && {
35
+ test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp)
36
+ }
37
+
38
+ t_begin "reset GC" && {
39
+ test xfalse = x$(curl -vsSf -X POST http://$listen/gc_reset 2>> $tmp)
40
+ }
41
+
42
+ t_begin "test default is noop" && {
43
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
44
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
45
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
46
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
47
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
48
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
49
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
50
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
51
+ test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
52
+ }
53
+
54
+ t_begin "4 bad requests to bump counter" && {
55
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
56
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
57
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
58
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
59
+ }
60
+
61
+ t_begin "GC-starting request returns immediately" && {
62
+ test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
63
+ }
64
+
65
+ t_begin "GC was started after 5 requests" && {
66
+ test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp)
67
+ }
68
+
69
+ t_begin "killing succeeds" && {
70
+ kill -QUIT $unicorn_pid
71
+ }
72
+
73
+ t_begin "check_stderr" && check_stderr
74
+
75
+ t_done
@@ -0,0 +1,129 @@
1
+ #!/bin/sh
2
+ # Copyright (c) 2009 Rainbows! hackers
3
+ # Copyright (c) 2010 Unicorn hackers
4
+ . ./my-tap-lib.sh
5
+
6
+ set +u
7
+
8
+ # sometimes we rely on http_proxy to avoid wasting bandwidth with Isolate
9
+ # and multiple Ruby versions
10
+ NO_PROXY=${UNICORN_TEST_ADDR-127.0.0.1}
11
+ export NO_PROXY
12
+
13
+ set -e
14
+ RUBY="${RUBY-ruby}"
15
+ RUBY_VERSION=${RUBY_VERSION-$($RUBY -e 'puts RUBY_VERSION')}
16
+ RUBY_ENGINE=${RUBY_ENGINE-$($RUBY -e 'puts((RUBY_ENGINE rescue "ruby"))')}
17
+ t_pfx=$PWD/trash/$T-$RUBY_ENGINE-$RUBY_VERSION
18
+ set -u
19
+
20
+ PATH=$PWD/bin:$PATH
21
+ export PATH
22
+
23
+ test -x $PWD/bin/unused_listen || die "must be run in 't' directory"
24
+
25
+ wait_for_pid () {
26
+ path="$1"
27
+ nr=30
28
+ while ! test -s "$path" && test $nr -gt 0
29
+ do
30
+ nr=$(($nr - 1))
31
+ sleep 1
32
+ done
33
+ }
34
+
35
+ # "unix_time" is not in POSIX, but in GNU, and FreeBSD 9.0 (possibly earlier)
36
+ unix_time () {
37
+ $RUBY -e 'puts Time.now.to_i'
38
+ }
39
+
40
+ # "wc -l" outputs leading whitespace on *BSDs, filter it out for portability
41
+ count_lines () {
42
+ wc -l | tr -d '[:space:]'
43
+ }
44
+
45
+ # "wc -c" outputs leading whitespace on *BSDs, filter it out for portability
46
+ count_bytes () {
47
+ wc -c | tr -d '[:space:]'
48
+ }
49
+
50
+ # given a list of variable names, create temporary files and assign
51
+ # the pathnames to those variables
52
+ rtmpfiles () {
53
+ for id in "$@"
54
+ do
55
+ name=$id
56
+
57
+ case $name in
58
+ *fifo)
59
+ _tmp=$t_pfx.$id
60
+ eval "$id=$_tmp"
61
+ rm -f $_tmp
62
+ mkfifo $_tmp
63
+ T_RM_LIST="$T_RM_LIST $_tmp"
64
+ ;;
65
+ *socket)
66
+ _tmp="$(mktemp -t $id.$$.XXXXXXXX)"
67
+ if test $(printf "$_tmp" |count_bytes) -gt 108
68
+ then
69
+ echo >&2 "$_tmp too long, tests may fail"
70
+ echo >&2 "Try to set TMPDIR to a shorter path"
71
+ fi
72
+ eval "$id=$_tmp"
73
+ rm -f $_tmp
74
+ T_RM_LIST="$T_RM_LIST $_tmp"
75
+ ;;
76
+ *)
77
+ _tmp=$t_pfx.$id
78
+ eval "$id=$_tmp"
79
+ > $_tmp
80
+ T_OK_RM_LIST="$T_OK_RM_LIST $_tmp"
81
+ ;;
82
+ esac
83
+ done
84
+ }
85
+
86
+ dbgcat () {
87
+ id=$1
88
+ eval '_file=$'$id
89
+ echo "==> $id <=="
90
+ sed -e "s/^/$id:/" < $_file
91
+ }
92
+
93
+ check_stderr () {
94
+ set +u
95
+ _r_err=${1-${r_err}}
96
+ set -u
97
+ if grep -v $T $_r_err | grep -i Error | \
98
+ grep -v NameError.*Unicorn::Waiter
99
+ then
100
+ die "Errors found in $_r_err"
101
+ elif grep SIGKILL $_r_err
102
+ then
103
+ die "SIGKILL found in $_r_err"
104
+ fi
105
+ }
106
+
107
+ # unicorn_setup
108
+ unicorn_setup () {
109
+ eval $(unused_listen)
110
+ port=$(expr $listen : '[^:]*:\([0-9]*\)')
111
+ host=$(expr $listen : '\([^:][^:]*\):[0-9][0-9]*')
112
+
113
+ rtmpfiles unicorn_config pid r_err r_out fifo tmp ok
114
+ cat > $unicorn_config <<EOF
115
+ listen "$listen"
116
+ pid "$pid"
117
+ stderr_path "$r_err"
118
+ stdout_path "$r_out"
119
+ EOF
120
+ }
121
+
122
+ unicorn_wait_start () {
123
+ # no need to play tricks with FIFOs since we got "ready_pipe" now
124
+ unicorn_pid=$(cat $pid)
125
+ }
126
+
127
+ rsha1 () {
128
+ sha1sum.rb
129
+ }
@@ -0,0 +1,11 @@
1
+ class WriteOnClose
2
+ def each(&block)
3
+ @callback = block
4
+ end
5
+
6
+ def close
7
+ @callback.call "7\r\nGoodbye\r\n0\r\n\r\n"
8
+ end
9
+ end
10
+ use Rack::ContentType, "text/plain"
11
+ run(lambda { |_| [ 200, [%w(Transfer-Encoding chunked)], WriteOnClose.new ] })
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/ruby -n
2
+ # -*- encoding: binary -*-
3
+
4
+ BEGIN { $tests = $assertions = $failures = $errors = 0 }
5
+
6
+ $_ =~ /(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/ or next
7
+ $tests += $1.to_i
8
+ $assertions += $2.to_i
9
+ $failures += $3.to_i
10
+ $errors += $4.to_i
11
+
12
+ END {
13
+ printf("\n%d tests, %d assertions, %d failures, %d errors\n",
14
+ $tests, $assertions, $failures, $errors)
15
+ }
@@ -0,0 +1,60 @@
1
+ = Performance
2
+
3
+ Unicorn is pretty fast, and we want it to get faster. Unicorn strives
4
+ to get HTTP requests to your application and write HTTP responses back
5
+ as quickly as possible. Unicorn does not do any background processing
6
+ while your app runs, so your app will get all the CPU time provided to
7
+ it by your OS kernel.
8
+
9
+ A gentle reminder: Unicorn is NOT for serving clients over slow network
10
+ connections. Use nginx (or something similar) to complement Unicorn if
11
+ you have slow clients.
12
+
13
+ == dd.ru
14
+
15
+ This is a pure I/O benchmark. In the context of Unicorn, this is the
16
+ only one that matters. It is a standard rackup-compatible .ru file and
17
+ may be used with other Rack-compatible servers.
18
+
19
+ unicorn -E none dd.ru
20
+
21
+ You can change the size and number of chunks in the response with
22
+ the "bs" and "count" environment variables. The following command
23
+ will cause dd.ru to return 4 chunks of 16384 bytes each, leading to
24
+ 65536 byte response:
25
+
26
+ bs=16384 count=4 unicorn -E none dd.ru
27
+
28
+ Or if you want to add logging (small performance impact):
29
+
30
+ unicorn -E deployment dd.ru
31
+
32
+ Eric runs then runs clients on a LAN it in several different ways:
33
+
34
+ client@host1 -> unicorn@host1(tcp)
35
+ client@host2 -> unicorn@host1(tcp)
36
+ client@host3 -> nginx@host1 -> unicorn@host1(tcp)
37
+ client@host3 -> nginx@host1 -> unicorn@host1(unix)
38
+ client@host3 -> nginx@host2 -> unicorn@host1(tcp)
39
+
40
+ The benchmark client is usually httperf.
41
+
42
+ Another gentle reminder: performance with slow networks/clients
43
+ is NOT our problem. That is the job of nginx (or similar).
44
+
45
+ == ddstream.ru
46
+
47
+ Standalone Rack app intended to show how BAD we are at slow clients.
48
+ See usage in comments.
49
+
50
+ == readinput.ru
51
+
52
+ Standalone Rack app intended to show how bad we are with slow uploaders.
53
+ See usage in comments.
54
+
55
+ == Contributors
56
+
57
+ This directory is intended to remain stable. Do not make changes
58
+ to benchmarking code which can change performance and invalidate
59
+ results across revisions. Instead, write new benchmarks and update
60
+ coments/documentation as necessary.
@@ -0,0 +1,18 @@
1
+ # This benchmark is the simplest test of the I/O facilities in
2
+ # unicorn. It is meant to return a fixed-sized blob to test
3
+ # the performance of things in Unicorn, _NOT_ the app.
4
+ #
5
+ # Adjusting this benchmark is done via the "bs" (byte size) and "count"
6
+ # environment variables. "count" designates the count of elements of
7
+ # "bs" length in the Rack response body. The defaults are bs=4096, count=1
8
+ # to return one 4096-byte chunk.
9
+ bs = ENV['bs'] ? ENV['bs'].to_i : 4096
10
+ count = ENV['count'] ? ENV['count'].to_i : 1
11
+ slice = (' ' * bs).freeze
12
+ body = (1..count).map { slice }.freeze
13
+ hdr = {
14
+ 'Content-Length' => (bs * count).to_s.freeze,
15
+ 'Content-Type' => 'text/plain'.freeze
16
+ }.freeze
17
+ response = [ 200, hdr, body ].freeze
18
+ run(lambda { |env| response })
@@ -0,0 +1,50 @@
1
+ # This app is intended to test large HTTP responses with or without
2
+ # a fully-buffering reverse proxy such as nginx. Without a fully-buffering
3
+ # reverse proxy, unicorn will be unresponsive when client count exceeds
4
+ # worker_processes.
5
+ #
6
+ # To demonstrate how bad unicorn is at slowly reading clients:
7
+ #
8
+ # # in one terminal, start unicorn with one worker:
9
+ # unicorn -E none -l 127.0.0.1:8080 test/benchmark/ddstream.ru
10
+ #
11
+ # # in a different terminal, start more slow curl processes than
12
+ # # unicorn workers and watch time outputs
13
+ # curl --limit-rate 8K --trace-time -vsN http://127.0.0.1:8080/ >/dev/null &
14
+ # curl --limit-rate 8K --trace-time -vsN http://127.0.0.1:8080/ >/dev/null &
15
+ # wait
16
+ #
17
+ # The last client won't see a response until the first one is done reading
18
+ #
19
+ # nginx note: do not change the default "proxy_buffering" behavior.
20
+ # Setting "proxy_buffering off" prevents nginx from protecting unicorn.
21
+
22
+ # totally standalone rack app to stream a giant response
23
+ class BigResponse
24
+ def initialize(bs, count)
25
+ @buf = "#{bs.to_s(16)}\r\n#{' ' * bs}\r\n"
26
+ @count = count
27
+ @res = [ 200,
28
+ { 'Transfer-Encoding' => -'chunked', 'Content-Type' => 'text/plain' },
29
+ self
30
+ ]
31
+ end
32
+
33
+ # rack response body iterator
34
+ def each
35
+ (1..@count).each { yield @buf }
36
+ yield -"0\r\n\r\n"
37
+ end
38
+
39
+ # rack app entry endpoint
40
+ def call(_env)
41
+ @res
42
+ end
43
+ end
44
+
45
+ # default to a giant (128M) response because kernel socket buffers
46
+ # can be ridiculously large on some systems
47
+ bs = ENV['bs'] ? ENV['bs'].to_i : 65536
48
+ count = ENV['count'] ? ENV['count'].to_i : 2048
49
+ warn "serving response with bs=#{bs} count=#{count} (#{bs*count} bytes)"
50
+ run BigResponse.new(bs, count)
@@ -0,0 +1,40 @@
1
+ # This app is intended to test large HTTP requests with or without
2
+ # a fully-buffering reverse proxy such as nginx. Without a fully-buffering
3
+ # reverse proxy, unicorn will be unresponsive when client count exceeds
4
+ # worker_processes.
5
+
6
+ DOC = <<DOC
7
+ To demonstrate how bad unicorn is at slowly uploading clients:
8
+
9
+ # in one terminal, start unicorn with one worker:
10
+ unicorn -E none -l 127.0.0.1:8080 test/benchmark/readinput.ru
11
+
12
+ # in a different terminal, upload 45M from multiple curl processes:
13
+ dd if=/dev/zero bs=45M count=1 | curl -T- -HExpect: --limit-rate 1M \
14
+ --trace-time -v http://127.0.0.1:8080/ &
15
+ dd if=/dev/zero bs=45M count=1 | curl -T- -HExpect: --limit-rate 1M \
16
+ --trace-time -v http://127.0.0.1:8080/ &
17
+ wait
18
+
19
+ # The last client won't see a response until the first one is done uploading
20
+ # You also won't be able to make GET requests to view this documentation
21
+ # while clients are uploading. You can also view the stderr debug output
22
+ # of unicorn (see logging code in #{__FILE__}).
23
+ DOC
24
+
25
+ run(lambda do |env|
26
+ input = env['rack.input']
27
+ buf = ''.b
28
+
29
+ # default logger contains timestamps, rely on that so users can
30
+ # see what the server is doing
31
+ l = env['rack.logger']
32
+
33
+ l.debug('BEGIN reading input ...') if l
34
+ :nop while input.read(16384, buf)
35
+ l.debug('DONE reading input ...') if l
36
+
37
+ buf.clear
38
+ [ 200, [ %W(Content-Length #{DOC.size}), %w(Content-Type text/plain) ],
39
+ [ DOC ] ]
40
+ end)
@@ -0,0 +1,8 @@
1
+ run(lambda { |env|
2
+ body = "#{caller.size}\n"
3
+ h = {
4
+ "Content-Length" => body.size.to_s,
5
+ "Content-Type" => "text/plain",
6
+ }
7
+ [ 200, h, [ body ] ]
8
+ })
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/perl -w
2
+ # Benchmark script to spawn some processes and hammer a local unicorn
3
+ # to test accept loop performance. This only does Unix sockets.
4
+ # There's plenty of TCP benchmarking tools out there, and TCP port reuse
5
+ # has predictability problems since unicorn can't do persistent connections.
6
+ # Written in Perl for the same reason: predictability.
7
+ # Ruby GC is not as predictable as Perl refcounting.
8
+ use strict;
9
+ use Socket qw(AF_UNIX SOCK_STREAM sockaddr_un);
10
+ use POSIX qw(:sys_wait_h);
11
+ use Getopt::Std;
12
+ # -c / -n switches stolen from ab(1)
13
+ my $usage = "$0 [-c CONCURRENCY] [-n NUM_REQUESTS] SOCKET_PATH\n";
14
+ our $opt_c = 2;
15
+ our $opt_n = 1000;
16
+ getopts('c:n:') or die $usage;
17
+ my $unix_path = shift or die $usage;
18
+ use constant REQ => "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
19
+ use constant REQ_LEN => length(REQ);
20
+ use constant BUFSIZ => 8192;
21
+ $^F = 99; # don't waste syscall time with FD_CLOEXEC
22
+
23
+ my %workers; # pid => worker num
24
+ die "-n $opt_n not evenly divisible by -c $opt_c\n" if $opt_n % $opt_c;
25
+ my $n_per_worker = $opt_n / $opt_c;
26
+ my $addr = sockaddr_un($unix_path);
27
+
28
+ for my $num (1..$opt_c) {
29
+ defined(my $pid = fork) or die "fork failed: $!\n";
30
+ if ($pid) {
31
+ $workers{$pid} = $num;
32
+ } else {
33
+ work($n_per_worker);
34
+ }
35
+ }
36
+
37
+ reap_worker(0) while scalar keys %workers;
38
+ exit;
39
+
40
+ sub work {
41
+ my ($n) = @_;
42
+ my ($buf, $x);
43
+ for (1..$n) {
44
+ socket(S, AF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
45
+ connect(S, $addr) or die "connect: $!";
46
+ defined($x = syswrite(S, REQ)) or die "write: $!";
47
+ $x == REQ_LEN or die "short write: $x != ".REQ_LEN."\n";
48
+ do {
49
+ $x = sysread(S, $buf, BUFSIZ);
50
+ unless (defined $x) {
51
+ next if $!{EINTR};
52
+ die "sysread: $!\n";
53
+ }
54
+ } until ($x == 0);
55
+ }
56
+ exit 0;
57
+ }
58
+
59
+ sub reap_worker {
60
+ my ($flags) = @_;
61
+ my $pid = waitpid(-1, $flags);
62
+ return if !defined $pid || $pid <= 0;
63
+ my $p = delete $workers{$pid} || '(unknown)';
64
+ warn("$pid [$p] exited with $?\n") if $?;
65
+ $p;
66
+ }
@@ -0,0 +1,5 @@
1
+ These tests require the "unicorn" executable script to be installed in
2
+ PATH and rack being directly "require"-able ("rubygems" will not be
3
+ loaded for you). The tester is responsible for setting up RUBYLIB and
4
+ PATH environment variables (or running tests via GNU Make instead of
5
+ Rake).