raptor 0.10.0 → 0.12.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b7d4b6790a256864f0c2b4e8d061231c372a110493ef2846f547f4566232d5d
4
- data.tar.gz: dc6454ad796395d9eb7ab81327410ddd2004f0e1dd0bb03857636c508e84f7bc
3
+ metadata.gz: 36b617c828f29b9196e8e5b2ea86e6fdeb5c51fece8d5f2678df486ef77c5bd6
4
+ data.tar.gz: 433b1070b29e3b13d2b337a25ac7f6519c10c5ae8ab757b523ad93f426cf2f5f
5
5
  SHA512:
6
- metadata.gz: 6c0198c8697a569b7caf4492cf80c64edfbe7e6d0c1b4d7be7880175655bfa36b89040d3ab5b9597db995ac469eed26a1c74b7bb7c0c3206c9c47193b3930a48
7
- data.tar.gz: 6a73d6a927a118dea756b8012108dbdaf1f2462ea9ea5a6fbd4dabd56cfffa51a23f059f2c51c39cd5a4f41a3fc0e752022cd1963115edacecb3cd53e56b83fe
6
+ metadata.gz: 24e001cc6d45a3cc126f1bfdc1eb332bb0dc2353cb9ebbcaaa7bb0f111dc3c0f61715ac105700e5cf330c2fd9f4e514bea24610ec0242a15a446fd990489f368
7
+ data.tar.gz: e852c7851d772da17e28650b6e9fae59a9fa34619ed4aeba38d506febb0aaa5ff6096e5ffea20841822f81fcc0588c44a2dad30a32407cb37126bfe118e8ebe4
@@ -18,6 +18,25 @@ steps:
18
18
  - bundle install
19
19
  - bundle exec rake ci
20
20
 
21
+ - label: ":ruby: Ruby 4.0 +GC.stress"
22
+ image: "ruby:4.0"
23
+ env:
24
+ RUBY_GC_STRESS: "1"
25
+ commands:
26
+ - ruby -v
27
+ - bundle install
28
+ - bundle exec rake ci
29
+
30
+ - label: ":ruby: Ruby 4.0 +YJIT +GC.stress"
31
+ image: "ruby:4.0"
32
+ env:
33
+ RUBY_YJIT_ENABLE: "1"
34
+ RUBY_GC_STRESS: "1"
35
+ commands:
36
+ - ruby -v
37
+ - bundle install
38
+ - bundle exec rake ci
39
+
21
40
  - label: ":ruby: Ruby head"
22
41
  soft_fail: true
23
42
  image: "rubylang/ruby:master-dev"
@@ -38,6 +57,29 @@ steps:
38
57
  - bundle install
39
58
  - bundle exec rake ci
40
59
 
60
+ - label: ":ruby: Ruby head +GC.stress"
61
+ soft_fail: true
62
+ image: "rubylang/ruby:master-dev"
63
+ env:
64
+ RUBY_GC_STRESS: "1"
65
+ commands:
66
+ - apt-get update && apt-get install -y libyaml-dev
67
+ - ruby -v
68
+ - bundle install
69
+ - bundle exec rake ci
70
+
71
+ - label: ":ruby: Ruby head +YJIT +GC.stress"
72
+ soft_fail: true
73
+ image: "rubylang/ruby:master-dev"
74
+ env:
75
+ RUBY_YJIT_ENABLE: "1"
76
+ RUBY_GC_STRESS: "1"
77
+ commands:
78
+ - apt-get update && apt-get install -y libyaml-dev
79
+ - ruby -v
80
+ - bundle install
81
+ - bundle exec rake ci
82
+
41
83
  - group: ":mac: macOS"
42
84
  key: macos
43
85
  steps:
@@ -65,6 +107,33 @@ steps:
65
107
  - bundle install
66
108
  - bundle exec rake ci
67
109
 
110
+ - label: ":ruby: Ruby 4.0 +GC.stress"
111
+ agents:
112
+ queue: macos
113
+ env:
114
+ RUBY_GC_STRESS: "1"
115
+ commands:
116
+ - brew install --quiet ruby@4.0
117
+ - export PATH="$(brew --prefix ruby@4.0)/bin:$PATH"
118
+ - bundle config set --local path .bundle
119
+ - ruby -v
120
+ - bundle install
121
+ - bundle exec rake ci
122
+
123
+ - label: ":ruby: Ruby 4.0 +YJIT +GC.stress"
124
+ agents:
125
+ queue: macos
126
+ env:
127
+ RUBY_YJIT_ENABLE: "1"
128
+ RUBY_GC_STRESS: "1"
129
+ commands:
130
+ - brew install --quiet ruby@4.0
131
+ - export PATH="$(brew --prefix ruby@4.0)/bin:$PATH"
132
+ - bundle config set --local path .bundle
133
+ - ruby -v
134
+ - bundle install
135
+ - bundle exec rake ci
136
+
68
137
  - label: ":ruby: Ruby head"
69
138
  soft_fail: true
70
139
  agents:
@@ -92,3 +161,34 @@ steps:
92
161
  - ruby -v
93
162
  - bundle install
94
163
  - bundle exec rake ci
164
+
165
+ - label: ":ruby: Ruby head +GC.stress"
166
+ soft_fail: true
167
+ agents:
168
+ queue: macos
169
+ env:
170
+ RUBY_GC_STRESS: "1"
171
+ commands:
172
+ - brew unlink ruby
173
+ - brew install --HEAD --quiet ruby
174
+ - export PATH="$(brew --prefix ruby)/bin:$PATH"
175
+ - bundle config set --local path .bundle
176
+ - ruby -v
177
+ - bundle install
178
+ - bundle exec rake ci
179
+
180
+ - label: ":ruby: Ruby head +YJIT +GC.stress"
181
+ soft_fail: true
182
+ agents:
183
+ queue: macos
184
+ env:
185
+ RUBY_YJIT_ENABLE: "1"
186
+ RUBY_GC_STRESS: "1"
187
+ commands:
188
+ - brew unlink ruby
189
+ - brew install --HEAD --quiet ruby
190
+ - export PATH="$(brew --prefix ruby)/bin:$PATH"
191
+ - bundle config set --local path .bundle
192
+ - ruby -v
193
+ - bundle install
194
+ - bundle exec rake ci
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.12.0] - 2026-07-19
4
+
5
+ - Add `refork_after` and `before_refork` for reforking workers off a warmed source
6
+ - Add `before_fork`, `before_worker_boot`, and `before_worker_shutdown` hooks
7
+ - Sync `$stdout` and `$stderr` writes so info-level logs flush immediately
8
+ - Break reuseport routing ties by 4-tuple hash instead of a random draw
9
+
10
+ ## [0.11.0] - 2026-07-12
11
+
12
+ - Yield subsequent HTTP/1.1 keep-alive requests to the thread pool only under saturation
13
+ - Reuse a per-thread HTTP/1.1 parser across requests
14
+ - Skip a per-response allocation when formatting response headers
15
+ - Reject HTTP/2 streams with malformed pseudo-headers with `RST_STREAM`
16
+ - Populate `PATH_INFO` from absolute-form request targets
17
+ - Consume the trailer section after the chunked-body terminator
18
+ - Reject request headers larger than 112KB with 400
19
+ - Reject chunk sizes containing non-hex characters with 400
20
+ - Advance the parser's `nread` past the request header terminator
21
+ - Detect chunked `Transfer-Encoding` case-insensitively
22
+ - Reject HTTP/1.1 requests without a valid `Host` header with 400
23
+
3
24
  ## [0.10.0] - 2026-07-07
4
25
 
5
26
  - Memoize the server port string for the Rack env
data/README.md CHANGED
@@ -36,23 +36,23 @@ run proc { |_env| [200, { "content-type" => "text/plain" }, ["Hello, World!"]] }
36
36
 
37
37
  ```
38
38
  > bundle exec raptor -w 4 -t 3 hello_world.ru
39
- [Raptor 76577|Main|Main] Cluster initializing:
40
- [Raptor 76577|Main|Main] ├─ Version: 0.9.0
41
- [Raptor 76577|Main|Main] ├─ Ruby Version: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +YJIT +PRISM [arm64-darwin23]
42
- [Raptor 76577|Main|Main] ├─ Environment: development
43
- [Raptor 76577|Main|Main] ├─ Master PID: 76577
44
- [Raptor 76577|Main|Main] │ └─ 4 worker processes
45
- [Raptor 76577|Main|Main] │ ├─ 1 server thread
46
- [Raptor 76577|Main|Main] │ ├─ 1 reactor thread
47
- [Raptor 76577|Main|Main] │ ├─ 1 pipeline ractor
48
- [Raptor 76577|Main|Main] │ ├─ 1 pipeline collector thread
49
- [Raptor 76577|Main|Main] │ ├─ 3 worker threads
50
- [Raptor 76577|Main|Main] │ └─ 1 stats thread
51
- [Raptor 76577|Main|Main] └─ Listening on 0.0.0.0:9292
52
- [Raptor 76579|Main|Main] Worker 0 booted
53
- [Raptor 76580|Main|Main] Worker 1 booted
54
- [Raptor 76581|Main|Main] Worker 2 booted
55
- [Raptor 76582|Main|Main] Worker 3 booted
39
+ [Raptor 59013|Main|Main] Cluster initializing:
40
+ [Raptor 59013|Main|Main] ├─ Version: 0.12.0
41
+ [Raptor 59013|Main|Main] ├─ Ruby Version: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +YJIT +PRISM [arm64-darwin23]
42
+ [Raptor 59013|Main|Main] ├─ Environment: development
43
+ [Raptor 59013|Main|Main] ├─ Master PID: 59013
44
+ [Raptor 59013|Main|Main] │ └─ 4 worker processes
45
+ [Raptor 59013|Main|Main] │ ├─ 1 server thread
46
+ [Raptor 59013|Main|Main] │ ├─ 1 reactor thread
47
+ [Raptor 59013|Main|Main] │ ├─ 1 pipeline ractor
48
+ [Raptor 59013|Main|Main] │ ├─ 1 pipeline collector thread
49
+ [Raptor 59013|Main|Main] │ ├─ 3 worker threads
50
+ [Raptor 59013|Main|Main] │ └─ 1 stats thread
51
+ [Raptor 59013|Main|Main] └─ Listening on 0.0.0.0:9292
52
+ [Raptor 59023|Main|Main] Worker 0 booted
53
+ [Raptor 59024|Main|Main] Worker 1 booted
54
+ [Raptor 59025|Main|Main] Worker 2 booted
55
+ [Raptor 59026|Main|Main] Worker 3 booted
56
56
  ```
57
57
 
58
58
  ```
@@ -79,15 +79,16 @@ The config file is a Ruby file that evaluates to a hash of options. By default R
79
79
  ```ruby
80
80
  # raptor.rb
81
81
 
82
+ # Every key below is set to its default value; only include the ones you want to override.
82
83
  {
83
84
  binds: ["tcp://0.0.0.0:9292"],
84
85
  socket_backlog: 1024,
85
86
  drain_accept_queue: false,
86
- workers: 4,
87
+ workers: 4, # `Etc.nprocessors`
87
88
  ractors: 1,
88
89
  threads: 3,
89
90
  chdir: nil,
90
- environment: nil,
91
+ environment: nil, # falls back to `RAILS_ENV`, then `RACK_ENV`, then `"development"`
91
92
  connection: {
92
93
  first_data_timeout: 30,
93
94
  chunk_data_timeout: 10,
@@ -106,6 +107,11 @@ The config file is a Ruby file that evaluates to a hash of options. By default R
106
107
  worker_timeout: 60,
107
108
  worker_drain_timeout: 25,
108
109
  worker_shutdown_timeout: 30,
110
+ refork_after: 1000, # `nil` on non-Linux
111
+ before_fork: [],
112
+ before_worker_boot: [],
113
+ before_worker_shutdown: [],
114
+ before_refork: [],
109
115
  stats_file: "tmp/raptor.json",
110
116
  pid_file: nil,
111
117
  stdout_file: nil,
@@ -187,20 +193,30 @@ Worker 1 (phase 0): pid=91351, requests=1199, busy=1/3, backlog=0, booted, last_
187
193
 
188
194
  ## (Micro) Benchmarks
189
195
 
190
- Raptor 0.10.0 vs Puma 8.0.2, median of 3 runs across two workload profiles: IO-bound (sleep for a random 5-50ms then
191
- return small JSON) and CPU-bound (serialise a JSON array of 20-200 items).
192
-
193
- | Protocol | Workload | Raptor | Puma | +/- vs Puma |
194
- | --------------------- | -------- | ------------ | ------------ | ----------- |
195
- | HTTP/1.1 | IO | 0.43k req/s | 0.41k req/s | +4.0% |
196
- | HTTP/1.1 | CPU | 10.99k req/s | 9.22k req/s | +19.1% |
197
- | HTTP/1.1 (keep-alive) | IO | 0.41k req/s | 0.40k req/s | +2.6% |
198
- | HTTP/1.1 (keep-alive) | CPU | 27.42k req/s | 25.75k req/s | +6.5% |
199
- | HTTP/2 | IO | 0.31k req/s | N/A | - |
200
- | HTTP/2 | CPU | 26.28k req/s | N/A | - |
196
+ Raptor 0.12.0 vs Puma 8.0.2 vs Falcon 0.55.5 across two workload profiles. **IO-bound** is a GET endpoint that
197
+ interleaves 5-10 short sleeps (total 2.5-15ms) with small CPU work, simulating a read path that makes several DB or
198
+ cache calls. **CPU-bound** is a POST endpoint that accepts a small JSON body, interleaves 3-5 chunks of JSON item
199
+ building (total 450-1500 items) with sub-100µs sleeps, and returns the built array, simulating a write path that does
200
+ most of its work in Ruby with a few near-zero-cost cache hits.
201
+
202
+ Each cell reports the median throughput and median p95 latency independently across 5 runs, so the two numbers in a row
203
+ may come from different runs. Every run starts a fresh server process so the samples are independent of each other;
204
+ state accumulated in a previous run cannot bias the next. Across the whole table, the widest spread
205
+ ((max - min) / 2 / median) between runs of a single cell was ±22.4% for throughput
206
+ and ±31.1% for p95.
207
+
208
+ | Protocol | Workload | Raptor req/s | Raptor p95 | Puma req/s | Puma p95 | vs Puma req/s | vs Puma p95 | Falcon req/s | Falcon p95 | vs Falcon req/s | vs Falcon p95 |
209
+ | --------------------- | -------- | ------------ | ---------- | ----------- | -------- | ------------- | ----------- | ------------ | ---------- | --------------- | ------------- |
210
+ | HTTP/1.1 | IO | 1.36k req/s | 52.90 ms | 0.94k req/s | 66.00 ms | +44.6% | -19.8% | 4.65k req/s | 14.60 ms | -70.8% | +262.3% |
211
+ | HTTP/1.1 | CPU | 3.46k req/s | 28.10 ms | 3.58k req/s | 16.70 ms | -3.3% | +68.3% | 3.57k req/s | 16.30 ms | -3.1% | +72.4% |
212
+ | HTTP/1.1 (keep-alive) | IO | 1.33k req/s | 34.60 ms | 0.94k req/s | 65.40 ms | +41.6% | -47.1% | 4.17k req/s | 16.70 ms | -68.1% | +107.2% |
213
+ | HTTP/1.1 (keep-alive) | CPU | 4.04k req/s | 12.10 ms | 3.73k req/s | 17.50 ms | +8.4% | -30.9% | 3.70k req/s | 17.90 ms | +9.1% | -32.4% |
214
+ | HTTP/2 | IO | 0.69k req/s | 87.49 ms | N/A | N/A | - | - | 4.04k req/s | 17.11 ms | -83.0% | +411.3% |
215
+ | HTTP/2 | CPU | 3.23k req/s | 22.63 ms | N/A | N/A | - | - | 3.85k req/s | 24.38 ms | -16.2% | -7.2% |
201
216
 
202
217
  > ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +YJIT +PRISM [aarch64-linux]
203
- > 4 workers, 3 threads, 24 concurrent connections
218
+ > 4 worker processes; Raptor and Puma run 3 threads per worker, Falcon runs unbounded fibers per worker;
219
+ > 48 concurrent HTTP/1.1 client connections; 16 concurrent HTTP/2 client connections × 3 streams each
204
220
 
205
221
  See [bin/benchmark](bin/benchmark) for more details.
206
222