raptor 0.23.0 → 0.24.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 +4 -4
- data/CHANGELOG.md +16 -0
- data/Dockerfile +7 -1
- data/README.md +183 -68
- data/docs/assets/profile_picture.png +0 -0
- data/docs/assets/startup_output.svg +37 -0
- data/docs/raptor-vs-puma.md +103 -429
- data/docs/talk.md +262 -169
- data/ext/raptor_http/raptor_http.c +82 -123
- data/lib/rackup/handler/raptor.rb +2 -1
- data/lib/raptor/cli.rb +1 -0
- data/lib/raptor/cluster.rb +85 -39
- data/lib/raptor/control_server.rb +2 -0
- data/lib/raptor/http.rb +0 -1
- data/lib/raptor/http1.rb +52 -30
- data/lib/raptor/http2.rb +46 -13
- data/lib/raptor/plugin.rb +98 -0
- data/lib/raptor/version.rb +1 -1
- data/sig/generated/raptor/cluster.rbs +18 -5
- data/sig/generated/raptor/http.rbs +0 -2
- data/sig/generated/raptor/http1.rbs +21 -13
- data/sig/generated/raptor/http2.rbs +12 -9
- data/sig/generated/raptor/plugin.rbs +52 -0
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c8c3462777a399cad50b6131c497c98ab519850ff1d88d062b681cc05c9d540b
|
|
4
|
+
data.tar.gz: 878a2629b500d8873836cda4bd463f0dcb727a33bd301fc5a246cd860a3f0957
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0d9b05f416a7024c91dc2861d6f748eadb1c20e01224c3e82a1202247f48220e56f81742fa600f41f1885c60587464b9506c0e2855d9392767016f5199bb0d94
|
|
7
|
+
data.tar.gz: 93403bcdbfaef05e6a011cc795ef66b7713dc2ed4266c157afb3f5eb1b53ae60c8f7610e60d2caee75e8b82716e58cac6b771543d6f9d43823cb03e5eed87dd8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.24.0] - 2026-11-08
|
|
4
|
+
|
|
5
|
+
- Honour `connection.max_body_size` for HTTP/2 request bodies without closing other streams
|
|
6
|
+
- Wait for all current workers to boot before notifying systemd that Raptor is ready
|
|
7
|
+
- Prefer each over call for HTTP/1 Rack response bodies that implement both
|
|
8
|
+
- Reject empty HTTP/1 Content-Length values and unsupported transfer codings before reading request bodies
|
|
9
|
+
- Preserve request Version headers instead of replacing them with the HTTP protocol
|
|
10
|
+
- Trim leading tabs as optional HTTP/1 header whitespace
|
|
11
|
+
- Honour HTTP/1 Connection token lists, with close taking precedence over keep-alive
|
|
12
|
+
- Run worker boot hooks before starting application threads, parsers, and request handling
|
|
13
|
+
- Close HTTP/2 response bodies when writing fails or a stream is cancelled
|
|
14
|
+
- Bound HTTP/1 chunk size lines and trailers, including incomplete metadata
|
|
15
|
+
- Reject invalid CRLF delimiters after HTTP/1 chunk payloads
|
|
16
|
+
- Prefer hyphenated request headers over underscore aliases and reject HTTP/1 framing aliases
|
|
17
|
+
- Add plugins with lifecycle hooks, cluster stats, and managed background threads
|
|
18
|
+
|
|
3
19
|
## [0.23.0] - 2026-10-18
|
|
4
20
|
|
|
5
21
|
- Route connections through BPF dispatch on every TCP bind
|
data/Dockerfile
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
FROM golang:bookworm AS hey-builder
|
|
2
|
-
RUN CGO_ENABLED=0 go install github.com/rakyll/hey@
|
|
2
|
+
RUN CGO_ENABLED=0 go install github.com/rakyll/hey@v0.1.5
|
|
3
|
+
|
|
4
|
+
WORKDIR /go/pkg/mod/github.com/rakyll/hey@v0.1.5
|
|
5
|
+
# Keep the bounded initial allocation, but retain every response for full-window p95.
|
|
6
|
+
RUN sed -i '/if len(r.resLats) < maxRes {/d; /r.offsets = append(r.offsets, res.offset.Seconds())/{n;d;}' requester/report.go \
|
|
7
|
+
&& gofmt -w requester/report.go \
|
|
8
|
+
&& CGO_ENABLED=0 go build -o /go/bin/hey .
|
|
3
9
|
|
|
4
10
|
FROM rubylang/ruby:master-dev
|
|
5
11
|
|
data/README.md
CHANGED
|
@@ -36,29 +36,29 @@ run proc { |_env| [200, { "content-type" => "text/plain" }, ["Hello, World!"]] }
|
|
|
36
36
|
|
|
37
37
|
```
|
|
38
38
|
> bundle exec raptor -w 10 -t 3 hello_world.ru
|
|
39
|
-
[Raptor
|
|
40
|
-
[Raptor
|
|
41
|
-
[Raptor
|
|
42
|
-
[Raptor
|
|
43
|
-
[Raptor
|
|
44
|
-
[Raptor
|
|
45
|
-
[Raptor
|
|
46
|
-
[Raptor
|
|
47
|
-
[Raptor
|
|
48
|
-
[Raptor
|
|
49
|
-
[Raptor
|
|
50
|
-
[Raptor
|
|
51
|
-
[Raptor
|
|
52
|
-
[Raptor
|
|
53
|
-
[Raptor
|
|
54
|
-
[Raptor
|
|
55
|
-
[Raptor
|
|
56
|
-
[Raptor
|
|
57
|
-
[Raptor
|
|
58
|
-
[Raptor
|
|
59
|
-
[Raptor
|
|
60
|
-
[Raptor
|
|
61
|
-
[Raptor
|
|
39
|
+
[Raptor 39704|Main|Main] Cluster initializing:
|
|
40
|
+
[Raptor 39704|Main|Main] ├─ Version: 0.23.0
|
|
41
|
+
[Raptor 39704|Main|Main] ├─ Ruby Version: ruby 4.0.9 (2026-10-23 revision 3e93b23afc) +YJIT +PRISM [arm64-darwin25]
|
|
42
|
+
[Raptor 39704|Main|Main] ├─ Environment: development
|
|
43
|
+
[Raptor 39704|Main|Main] ├─ Master PID: 39704
|
|
44
|
+
[Raptor 39704|Main|Main] │ └─ 10 worker processes
|
|
45
|
+
[Raptor 39704|Main|Main] │ ├─ 1 server thread
|
|
46
|
+
[Raptor 39704|Main|Main] │ ├─ 1 reactor thread
|
|
47
|
+
[Raptor 39704|Main|Main] │ ├─ 1 HTTP/1.1 pipeline ractor
|
|
48
|
+
[Raptor 39704|Main|Main] │ ├─ 1 pipeline collector thread
|
|
49
|
+
[Raptor 39704|Main|Main] │ ├─ 3 worker threads (scaling, no limit)
|
|
50
|
+
[Raptor 39704|Main|Main] │ └─ 1 stats thread
|
|
51
|
+
[Raptor 39704|Main|Main] └─ Listening on 0.0.0.0:9292
|
|
52
|
+
[Raptor 39720|Main|Main] Worker 1 booted
|
|
53
|
+
[Raptor 39719|Main|Main] Worker 0 booted
|
|
54
|
+
[Raptor 39722|Main|Main] Worker 3 booted
|
|
55
|
+
[Raptor 39721|Main|Main] Worker 2 booted
|
|
56
|
+
[Raptor 39723|Main|Main] Worker 4 booted
|
|
57
|
+
[Raptor 39725|Main|Main] Worker 6 booted
|
|
58
|
+
[Raptor 39724|Main|Main] Worker 5 booted
|
|
59
|
+
[Raptor 39728|Main|Main] Worker 8 booted
|
|
60
|
+
[Raptor 39726|Main|Main] Worker 7 booted
|
|
61
|
+
[Raptor 39730|Main|Main] Worker 9 booted
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
```
|
|
@@ -127,6 +127,7 @@ working directory. Pass `-c PATH` to point at a specific file.
|
|
|
127
127
|
before_worker_boot: [],
|
|
128
128
|
before_worker_shutdown: [],
|
|
129
129
|
before_refork: [],
|
|
130
|
+
plugins: [],
|
|
130
131
|
stats_file: "tmp/raptor.json",
|
|
131
132
|
control_url: nil,
|
|
132
133
|
pid_file: nil,
|
|
@@ -142,6 +143,46 @@ By default each worker adds threads beyond `threads` only while queued requests
|
|
|
142
143
|
database or network calls. It stops adding them once Ruby execution becomes the bottleneck, and the extra threads
|
|
143
144
|
retire when the queue is idle. Set `max_threads` to cap this growth, or set it to `threads` for a fixed pool.
|
|
144
145
|
|
|
146
|
+
## Plugins
|
|
147
|
+
|
|
148
|
+
Plugins start in the master process and can register lifecycle hooks that run in workers. Use them for metrics
|
|
149
|
+
exporters, probes, or other integrations. Enable them in your config with `plugins: [:stats_logger]`.
|
|
150
|
+
|
|
151
|
+
Raptor loads each name from `raptor/plugin/<name>` on Ruby's load path. A gem can provide that file, or you can require
|
|
152
|
+
an application-local plugin before returning the config hash.
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
# lib/raptor/plugin/stats_logger.rb
|
|
156
|
+
require "raptor/plugin"
|
|
157
|
+
|
|
158
|
+
Raptor::Plugin.create(:stats_logger) do
|
|
159
|
+
def start(cluster)
|
|
160
|
+
in_background do
|
|
161
|
+
loop do
|
|
162
|
+
Raptor::Log.info(JSON.generate(cluster.stats_hash))
|
|
163
|
+
sleep 10
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
For an existing class, inherit from `Raptor::Plugin` and register it with
|
|
171
|
+
`Raptor::Plugin.register(:stats_logger, MyStatsLogger)` instead.
|
|
172
|
+
|
|
173
|
+
`start(cluster)` runs once before the initial workers fork. `cluster.options` exposes configuration, including
|
|
174
|
+
plugin-specific keys. Append callbacks to its `before_fork`, `before_worker_boot`, `before_worker_shutdown`, and
|
|
175
|
+
`before_refork` arrays during startup. If your plugin opens a listener, close the worker's inherited copy with
|
|
176
|
+
`cluster.options[:before_worker_boot] << proc { @listener.close }` so only the master serves it.
|
|
177
|
+
|
|
178
|
+
`cluster.stats` returns per-worker snapshots. `cluster.stats_hash` returns the same aggregate structure as `GET /stats`,
|
|
179
|
+
including boot status, busy threads, capacity, backlog, and request counts. Both remain available while workers drain.
|
|
180
|
+
|
|
181
|
+
Override `stop` to close listeners and flush exporters. Raptor calls it after workers exit, in reverse plugin order,
|
|
182
|
+
then stops and joins threads created with `in_background`. These callbacks also run before hot restart and when startup
|
|
183
|
+
fails, so `stop` must handle partially initialized resources. Worker replacement and phased restart keep the same
|
|
184
|
+
master plugin instances running.
|
|
185
|
+
|
|
145
186
|
## Bindings
|
|
146
187
|
|
|
147
188
|
`binds` accepts any combination of these URIs.
|
|
@@ -170,7 +211,8 @@ to configuration, dependencies, or Raptor itself.
|
|
|
170
211
|
## systemd
|
|
171
212
|
|
|
172
213
|
Raptor supports socket activation and `sd_notify`, so it works with `Type=notify` units. When the socket unit is
|
|
173
|
-
active, Raptor serves the listening sockets systemd passes in place of `binds`.
|
|
214
|
+
active, Raptor serves the listening sockets systemd passes in place of `binds`. Raptor sends `READY=1` after all
|
|
215
|
+
workers have finished booting, including their `before_worker_boot` hooks.
|
|
174
216
|
|
|
175
217
|
```ini
|
|
176
218
|
# /etc/systemd/system/myapp.socket
|
|
@@ -208,50 +250,123 @@ Set `control_url` to a Unix socket URL such as `unix:///tmp/raptor-control.sock`
|
|
|
208
250
|
|
|
209
251
|
## (Micro) Benchmarks
|
|
210
252
|
|
|
211
|
-
Raptor 0.
|
|
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
|
-
|
|
253
|
+
Raptor 0.24.0 vs Puma 8.0.2 vs Falcon 0.57.0. Each case has 3 fresh-process samples, interleaved in seeded shuffled
|
|
254
|
+
rounds. Each sample warms up for 3s and measures for 15s. Metrics are independent medians. ± is (max − min) / 2 /
|
|
255
|
+
median, not a confidence interval. Failure counts below each table sum all samples, so a failed run cannot disappear in
|
|
256
|
+
a median. Throughput counts successful ordinary requests only.
|
|
257
|
+
|
|
258
|
+
Comparison columns show each server's change from Raptor's median for the baseline mode. Higher req/s is better. Lower
|
|
259
|
+
p95 is better. Falcon's measurements are repeated against each Raptor mode, not rerun.
|
|
260
|
+
|
|
261
|
+
**IO** interleaves 5–10 sleeps of 0.5–1.5ms with small JSON renders. **CPU** interleaves 3–5 larger JSON renders with
|
|
262
|
+
25–50µs sleeps. Both discard the rendered JSON and return a short response. **64 KiB body** sends a prebuilt response to
|
|
263
|
+
isolate response transfer. **SSE (native)** uses Raptor's detached body versus blocking Enumerators. **Raptor (enum)**
|
|
264
|
+
uses the same blocking body as Puma and Falcon, reusing their existing samples for comparison. The 20 streams are
|
|
265
|
+
cluster-wide connections, not guaranteed to be evenly placed. Streams without complete headers after 2s remain connected
|
|
266
|
+
and are counted as stalled.
|
|
267
|
+
|
|
268
|
+
Fixed (3), Scaling (3–16), and the IO-only Fixed (16) control separate tight concurrency, pool growth, and a prestarted
|
|
269
|
+
larger pool. Falcon uses unbounded fibers and runs once per workload/protocol. Raptor request-local cleanup, CPU
|
|
270
|
+
affinity, and reforking, and Puma's Fiber-per-request mode are disabled. Both threaded servers allow 999 requests per
|
|
271
|
+
keep-alive connection.
|
|
272
|
+
|
|
273
|
+
CPU includes the server master and descendants, including SSE event production, but excludes client CPU and warmup. CPU
|
|
274
|
+
ms/req divides that CPU time by successful ordinary requests. Peak aggregate PSS is sampled every 0.5s, proportionally
|
|
275
|
+
accounting for shared pages instead of counting them fully in every worker.
|
|
276
|
+
|
|
277
|
+
### IO over HTTP/1.1
|
|
278
|
+
|
|
279
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
280
|
+
| ------ | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
|
|
281
|
+
| Raptor | Fixed (3) | - | 3.32k ±0.2% | - | 50.10 | - | 2.387 | 364.0 |
|
|
282
|
+
| Raptor | Scaling (3–16) | - | 8.10k ±0.3% | - | 22.45 | - | 0.514 | 340.8 |
|
|
283
|
+
| Puma | Fixed (3) | Fixed (3) | 1.55k ±0.9% | 53.4% lower | 121.78 | 143.1% higher | 0.737 | 283.8 |
|
|
284
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 8.13k ±0.7% | 0.4% higher | 22.41 | 0.1% lower | 0.481 | 341.2 |
|
|
285
|
+
| Falcon | Fibers | Fixed (3) | 10.65k ±4.1% | 220.8% higher | 16.18 | 67.7% lower | 0.450 | 425.5 |
|
|
286
|
+
| Falcon | Fibers | Scaling (3–16) | 10.65k ±4.1% | 31.5% higher | 16.18 | 27.9% lower | 0.450 | 425.5 |
|
|
287
|
+
|
|
288
|
+
### IO over HTTP/1.1 keep-alive
|
|
289
|
+
|
|
290
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
291
|
+
| ------ | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
292
|
+
| Raptor | Fixed (3) | - | 3.01k ±8.2% | - | 56.38 | - | 2.306 | 365.0 |
|
|
293
|
+
| Raptor | Scaling (3–16) | - | 7.55k ±0.6% | - | 24.18 | - | 0.500 | 363.7 |
|
|
294
|
+
| Raptor | Fixed (16) | - | 7.56k ±0.7% | - | 24.16 | - | 0.468 | 367.8 |
|
|
295
|
+
| Puma | Fixed (3) | Fixed (3) | 1.49k ±0.2% | 50.4% lower | 105.33 | 86.8% higher | 0.784 | 290.7 |
|
|
296
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 7.63k ±0.9% | 1.1% higher | 23.89 | 1.2% lower | 0.466 | 329.9 |
|
|
297
|
+
| Puma | Fixed (16) | Fixed (16) | 7.73k ±0.5% | 2.2% higher | 23.55 | 2.5% lower | 0.461 | 332.3 |
|
|
298
|
+
| Falcon | Fibers | Fixed (3) | 7.54k ±1.8% | 150.8% higher | 24.40 | 56.7% lower | 0.373 | 357.4 |
|
|
299
|
+
| Falcon | Fibers | Scaling (3–16) | 7.54k ±1.8% | 0.1% lower | 24.40 | 0.9% higher | 0.373 | 357.4 |
|
|
300
|
+
| Falcon | Fibers | Fixed (16) | 7.54k ±1.8% | 0.2% lower | 24.40 | 1.0% higher | 0.373 | 357.4 |
|
|
301
|
+
|
|
302
|
+
### IO over HTTP/2
|
|
303
|
+
|
|
304
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
305
|
+
| ------ | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
306
|
+
| Raptor | Fixed (3) | - | 1.60k ±6.4% | - | 119.04 | - | 0.779 | 418.0 |
|
|
307
|
+
| Raptor | Scaling (3–16) | - | 7.98k ±9.9% | - | 23.38 | - | 0.565 | 894.4 |
|
|
308
|
+
| Falcon | Fibers | Fixed (3) | 7.18k ±1.3% | 348.7% higher | 26.29 | 77.9% lower | 0.438 | 515.8 |
|
|
309
|
+
| Falcon | Fibers | Scaling (3–16) | 7.18k ±1.3% | 10.0% lower | 26.29 | 12.4% higher | 0.438 | 515.8 |
|
|
310
|
+
|
|
311
|
+
### CPU over HTTP/1.1
|
|
312
|
+
|
|
313
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
314
|
+
| ------ | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
315
|
+
| Raptor | Fixed (3) | - | 3.13k ±0.3% | - | 72.60 | - | 2.673 | 526.0 |
|
|
316
|
+
| Raptor | Scaling (3–16) | - | 3.22k ±2.0% | - | 68.49 | - | 2.546 | 520.0 |
|
|
317
|
+
| Puma | Fixed (3) | Fixed (3) | 2.98k ±0.7% | 4.8% lower | 62.70 | 13.6% lower | 2.615 | 474.7 |
|
|
318
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 2.64k ±3.2% | 17.9% lower | 59.81 | 12.7% lower | 2.522 | 567.4 |
|
|
319
|
+
| Falcon | Fibers | Fixed (3) | 3.65k ±7.0% | 16.4% higher | 46.10 | 36.5% lower | 2.311 | 389.2 |
|
|
320
|
+
| Falcon | Fibers | Scaling (3–16) | 3.65k ±7.0% | 13.3% higher | 46.10 | 32.7% lower | 2.311 | 389.2 |
|
|
321
|
+
|
|
322
|
+
### CPU over HTTP/1.1 keep-alive
|
|
323
|
+
|
|
324
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
325
|
+
| ------ | -------------- | --------------- | ----------- | --------------- | ------ | ------------- | ---------- | ------- |
|
|
326
|
+
| Raptor | Fixed (3) | - | 2.88k ±1.6% | - | 57.40 | - | 2.721 | 515.4 |
|
|
327
|
+
| Raptor | Scaling (3–16) | - | 2.81k ±3.8% | - | 56.14 | - | 2.721 | 528.2 |
|
|
328
|
+
| Puma | Fixed (3) | Fixed (3) | 3.24k ±0.7% | 12.3% higher | 60.73 | 5.8% higher | 2.449 | 406.4 |
|
|
329
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 2.71k ±3.6% | 3.3% lower | 70.56 | 25.7% higher | 2.459 | 487.6 |
|
|
330
|
+
| Falcon | Fibers | Fixed (3) | 3.62k ±1.0% | 25.8% higher | 62.03 | 8.1% higher | 2.369 | 542.0 |
|
|
331
|
+
| Falcon | Fibers | Scaling (3–16) | 3.62k ±1.0% | 29.1% higher | 62.03 | 10.5% higher | 2.369 | 542.0 |
|
|
332
|
+
|
|
333
|
+
### CPU over HTTP/2
|
|
334
|
+
|
|
335
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
336
|
+
| ------ | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
|
|
337
|
+
| Raptor | Fixed (3) | - | 3.12k ±1.3% | - | 65.66 | - | 2.439 | 587.6 |
|
|
338
|
+
| Raptor | Scaling (3–16) | - | 3.15k ±0.4% | - | 74.95 | - | 2.344 | 609.0 |
|
|
339
|
+
| Falcon | Fibers | Fixed (3) | 3.49k ±20.7% | 11.7% higher | 120.58 | 83.6% higher | 2.309 | 536.3 |
|
|
340
|
+
| Falcon | Fibers | Scaling (3–16) | 3.49k ±20.7% | 10.7% higher | 120.58 | 60.9% higher | 2.309 | 536.3 |
|
|
341
|
+
|
|
342
|
+
### 64 KiB body over HTTP/1.1 keep-alive
|
|
343
|
+
|
|
344
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
345
|
+
| ------ | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
|
|
346
|
+
| Raptor | Scaling (3–16) | - | 96.13k ±0.8% | - | 3.68 | - | 0.048 | 512.3 |
|
|
347
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 83.26k ±0.0% | 13.4% lower | 3.94 | 7.3% higher | 0.055 | 1344.6 |
|
|
348
|
+
| Falcon | Fibers | Scaling (3–16) | 98.30k ±0.5% | 2.3% higher | 3.89 | 5.7% higher | 0.051 | 471.5 |
|
|
349
|
+
|
|
350
|
+
### IO + SSE (native) over HTTP/1.1 keep-alive
|
|
351
|
+
|
|
352
|
+
| Server | Mode | Raptor baseline | req/s | vs Raptor req/s | p95 ms | vs Raptor p95 | CPU ms/req | PSS MiB |
|
|
353
|
+
| ------------- | -------------- | --------------- | ------------ | --------------- | ------ | ------------- | ---------- | ------- |
|
|
354
|
+
| Raptor | Fixed (3) | - | 3.01k ±4.9% | - | 51.22 | - | 2.286 | 369.6 |
|
|
355
|
+
| Raptor | Scaling (3–16) | - | 7.49k ±0.8% | - | 24.39 | - | 0.488 | 372.7 |
|
|
356
|
+
| Puma | Fixed (3) | Fixed (3) | 0.39k ±13.8% | 87.0% lower | 314.80 | 514.6% higher | 1.250 | 282.9 |
|
|
357
|
+
| Puma | Scaling (3–16) | Scaling (3–16) | 7.51k ±0.4% | 0.4% higher | 24.23 | 0.6% lower | 0.464 | 336.3 |
|
|
358
|
+
| Falcon | Fibers | Fixed (3) | 7.57k ±4.4% | 151.9% higher | 24.04 | 53.1% lower | 0.375 | 355.5 |
|
|
359
|
+
| Falcon | Fibers | Scaling (3–16) | 7.57k ±4.4% | 1.2% higher | 24.04 | 1.4% lower | 0.375 | 355.5 |
|
|
360
|
+
| Raptor (enum) | Fixed (3) | - | 0.88k ±0.3% | - | 63.76 | - | 7.972 | 362.6 |
|
|
361
|
+
|
|
362
|
+
Puma, Fixed (3) had 28 timeouts, 1 stalled stream across all samples.
|
|
363
|
+
|
|
364
|
+
Raptor (enum), Fixed (3) had 29 timeouts across all samples.
|
|
365
|
+
|
|
366
|
+
> ruby 4.1.0dev (2026-10-27T15:28:18Z HEAD 33ac6afea7) +YJIT +PRISM [aarch64-linux]
|
|
367
|
+
> 10 workers, 120 HTTP/1.1 client connections, 40 HTTP/2 connections × 3 streams.
|
|
368
|
+
|
|
369
|
+
Run [bin/benchmark](bin/benchmark) to reproduce.
|
|
255
370
|
|
|
256
371
|
## Development
|
|
257
372
|
|
|
Binary file
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1320" height="1008" viewBox="0 0 1320 1008" role="img" aria-labelledby="title description">
|
|
2
|
+
<title id="title">Raptor startup output</title>
|
|
3
|
+
<desc id="description">The complete startup example from the README, including every log prefix, the process tree, and all ten worker boot messages. Long lines wrap as they would in a terminal.</desc>
|
|
4
|
+
<rect x="1" y="1" width="1318" height="1006" rx="16" fill="#161b22" stroke="#30363d" stroke-width="2"/>
|
|
5
|
+
<path d="M1 60H1319" stroke="#30363d" stroke-width="2"/>
|
|
6
|
+
<circle cx="32" cy="30" r="8" fill="#ff5f57"/>
|
|
7
|
+
<circle cx="60" cy="30" r="8" fill="#febc2e"/>
|
|
8
|
+
<circle cx="88" cy="30" r="8" fill="#28c840"/>
|
|
9
|
+
<text x="660" y="37" text-anchor="middle" fill="#8b949e" font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="20">raptor</text>
|
|
10
|
+
<g font-family="ui-monospace, SFMono-Regular, Menlo, monospace" font-size="24" fill="#e6edf3" xml:space="preserve">
|
|
11
|
+
<text x="32" y="110">> bundle exec raptor -w 10 -t 3 hello_world.ru</text>
|
|
12
|
+
<text x="32" y="146">[Raptor 39704|Main|Main] Cluster initializing:</text>
|
|
13
|
+
<text x="32" y="182">[Raptor 39704|Main|Main] ├─ Version: 0.23.0</text>
|
|
14
|
+
<text x="32" y="218">[Raptor 39704|Main|Main] ├─ Ruby Version: ruby 4.0.9 (2026-10-23 revision 3e93b23afc) </text>
|
|
15
|
+
<text x="32" y="254">+YJIT +PRISM [arm64-darwin25]</text>
|
|
16
|
+
<text x="32" y="290">[Raptor 39704|Main|Main] ├─ Environment: development</text>
|
|
17
|
+
<text x="32" y="326">[Raptor 39704|Main|Main] ├─ Master PID: 39704</text>
|
|
18
|
+
<text x="32" y="362">[Raptor 39704|Main|Main] │ └─ 10 worker processes</text>
|
|
19
|
+
<text x="32" y="398">[Raptor 39704|Main|Main] │ ├─ 1 server thread</text>
|
|
20
|
+
<text x="32" y="434">[Raptor 39704|Main|Main] │ ├─ 1 reactor thread</text>
|
|
21
|
+
<text x="32" y="470">[Raptor 39704|Main|Main] │ ├─ 1 HTTP/1.1 pipeline ractor</text>
|
|
22
|
+
<text x="32" y="506">[Raptor 39704|Main|Main] │ ├─ 1 pipeline collector thread</text>
|
|
23
|
+
<text x="32" y="542">[Raptor 39704|Main|Main] │ ├─ 3 worker threads (scaling, no limit)</text>
|
|
24
|
+
<text x="32" y="578">[Raptor 39704|Main|Main] │ └─ 1 stats thread</text>
|
|
25
|
+
<text x="32" y="614">[Raptor 39704|Main|Main] └─ Listening on 0.0.0.0:9292</text>
|
|
26
|
+
<text x="32" y="650">[Raptor 39720|Main|Main] Worker 1 booted</text>
|
|
27
|
+
<text x="32" y="686">[Raptor 39719|Main|Main] Worker 0 booted</text>
|
|
28
|
+
<text x="32" y="722">[Raptor 39722|Main|Main] Worker 3 booted</text>
|
|
29
|
+
<text x="32" y="758">[Raptor 39721|Main|Main] Worker 2 booted</text>
|
|
30
|
+
<text x="32" y="794">[Raptor 39723|Main|Main] Worker 4 booted</text>
|
|
31
|
+
<text x="32" y="830">[Raptor 39725|Main|Main] Worker 6 booted</text>
|
|
32
|
+
<text x="32" y="866">[Raptor 39724|Main|Main] Worker 5 booted</text>
|
|
33
|
+
<text x="32" y="902">[Raptor 39728|Main|Main] Worker 8 booted</text>
|
|
34
|
+
<text x="32" y="938">[Raptor 39726|Main|Main] Worker 7 booted</text>
|
|
35
|
+
<text x="32" y="974">[Raptor 39730|Main|Main] Worker 9 booted</text>
|
|
36
|
+
</g>
|
|
37
|
+
</svg>
|