raptor 0.11.0 → 0.13.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: be4ff0cf1729c188fab8261b749c2a279616bd565dbad81d18f5a3e75311b734
4
- data.tar.gz: 0acc2ece57f69207a34696df792e45bf52bfce22bb7617c5ceb3113223c175f5
3
+ metadata.gz: b7a531c4a4d9cfe93de0c4e8d255d9eac6a09d59f9af6d3884231cd0a383aca5
4
+ data.tar.gz: 3155fd5b27d53b5a65a9be9cc36d139da801ad3ce33a188ea9a46c77289ee97e
5
5
  SHA512:
6
- metadata.gz: 787fabc9128f3c4e16a394dc5634ff8435916b60b68ff3f6d569b0db561f07af0c61ab5d17e7440301c850d87fbbe1f0dc3691274b1c060d1cbbd6f7bc84bfbf
7
- data.tar.gz: 26d154b6c0abbc63986262e1212e526bd9e4e492d06f9a86e723e73fd85afd142550a15324b55ad91b575633db2d0231f262aebb818f198e2de4c96c9afa8666
6
+ metadata.gz: 53bfe180b9db4a6d9f7fdb3ea2f11bf2f19b5fa81c54beb09e74caa189381a52587756c6acae9b18ce16a5500a278a0b737934bc9b5e129fe3002605ee2ac5c1
7
+ data.tar.gz: a235a90619e1a8c1935208d1c516280bf911335e075bc6e91d5be78d134c5cc385381dba899328ebc2f8da213753d31618f5328e5eec8d609a06cfb1c30b5cb8
@@ -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,16 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.13.0] - 2026-07-21
4
+
5
+ - Tune BPF reuseport routing to spread bursts across near-idle workers
6
+
7
+ ## [0.12.0] - 2026-07-19
8
+
9
+ - Add `refork_after` and `before_refork` for reforking workers off a warmed source
10
+ - Add `before_fork`, `before_worker_boot`, and `before_worker_shutdown` hooks
11
+ - Sync `$stdout` and `$stderr` writes so info-level logs flush immediately
12
+ - Break reuseport routing ties by 4-tuple hash instead of a random draw
13
+
3
14
  ## [0.11.0] - 2026-07-12
4
15
 
5
16
  - Yield subsequent HTTP/1.1 keep-alive requests to the thread pool only under saturation
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.11.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.13.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.11.0 vs Puma 8.0.2, median of 3 runs across two workload profiles: IO-bound (sleep for a random 1-10ms 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 | 2.05k req/s | 1.94k req/s | +5.7% |
196
- | HTTP/1.1 | CPU | 13.66k req/s | 9.21k req/s | +48.3% |
197
- | HTTP/1.1 (keep-alive) | IO | 2.08k req/s | 1.95k req/s | +6.6% |
198
- | HTTP/1.1 (keep-alive) | CPU | 27.85k req/s | 27.47k req/s | +1.4% |
199
- | HTTP/2 | IO | 0.96k req/s | N/A | - |
200
- | HTTP/2 | CPU | 28.92k req/s | N/A | - |
196
+ Raptor 0.13.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 ±30.0% for throughput
206
+ and ±22.8% 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.39k req/s | 50.20 ms | 0.96k req/s | 66.20 ms | 44.1% higher | 24.2% lower | 4.54k req/s | 15.00 ms | 69.4% lower | 234.7% higher |
211
+ | HTTP/1.1 | CPU | 4.55k req/s | 18.10 ms | 3.64k req/s | 16.50 ms | 24.9% higher | 9.7% higher | 3.87k req/s | 15.00 ms | 17.5% higher | 20.7% higher |
212
+ | HTTP/1.1 (keep-alive) | IO | 1.42k req/s | 30.00 ms | 0.92k req/s | 65.80 ms | 54.8% higher | 54.4% lower | 4.08k req/s | 16.70 ms | 65.3% lower | 79.6% higher |
213
+ | HTTP/1.1 (keep-alive) | CPU | 4.51k req/s | 11.20 ms | 3.77k req/s | 17.50 ms | 19.8% higher | 36.0% lower | 4.00k req/s | 16.50 ms | 12.9% higher | 32.1% lower |
214
+ | HTTP/2 | IO | 0.71k req/s | 85.84 ms | N/A | N/A | - | - | 3.88k req/s | 17.43 ms | 81.7% lower | 392.3% higher |
215
+ | HTTP/2 | CPU | 4.07k req/s | 21.85 ms | N/A | N/A | - | - | 4.33k req/s | 30.84 ms | 6.0% lower | 29.2% lower |
201
216
 
202
217
  > ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +YJIT +PRISM [aarch64-linux]
203
- > 4 workers, 3 threads, 48 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