raptor 0.7.0 → 0.9.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/.buildkite/pipeline.yml +90 -32
- data/.dockerignore +5 -0
- data/CHANGELOG.md +30 -0
- data/Dockerfile +28 -0
- data/README.md +159 -27
- data/Rakefile +19 -1
- data/docs/raptor-vs-puma.md +557 -0
- data/ext/raptor_bpf/reuseport_select.bpf.c +63 -0
- data/ext/raptor_http/extconf.rb +1 -1
- data/ext/raptor_native/extconf.rb +7 -0
- data/ext/raptor_native/raptor_native.c +99 -0
- data/lib/rackup/handler/raptor.rb +12 -2
- data/lib/raptor/binder.rb +139 -31
- data/lib/raptor/cli.rb +83 -22
- data/lib/raptor/cluster.rb +214 -33
- data/lib/raptor/http.rb +116 -0
- data/lib/raptor/{request.rb → http1.rb} +228 -99
- data/lib/raptor/http2.rb +85 -40
- data/lib/raptor/reactor.rb +22 -15
- data/lib/raptor/reuseport_bpf.rb +108 -0
- data/lib/raptor/server.rb +92 -43
- data/lib/raptor/stats.rb +1 -1
- data/lib/raptor/systemd.rb +69 -0
- data/lib/raptor/version.rb +1 -1
- data/sig/generated/raptor/binder.rbs +82 -5
- data/sig/generated/raptor/cli.rbs +2 -3
- data/sig/generated/raptor/cluster.rbs +91 -13
- data/sig/generated/raptor/http.rbs +65 -0
- data/sig/generated/raptor/{request.rbs → http1.rbs} +122 -35
- data/sig/generated/raptor/http2.rbs +46 -13
- data/sig/generated/raptor/reactor.rbs +18 -11
- data/sig/generated/raptor/reuseport_bpf.rbs +56 -0
- data/sig/generated/raptor/server.rbs +49 -21
- data/sig/generated/raptor/systemd.rbs +42 -0
- metadata +30 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6dcf0e8beb3e5b74822eff407c51fbb0e83445ab54f75c37dad2cab2f9113ec5
|
|
4
|
+
data.tar.gz: 9131a6153b10e93e2e0b717355645fe485a1db0af52c3472f07a35fa4f95d64f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8a020f0e5c42eb4755a69c790f891aa334369d2ec58c063516893a53785574290feca84ebdd9d072b11601129f720eb2d82f52a7abbd7e0aa7bf79b17c57705c
|
|
7
|
+
data.tar.gz: 3b90235078097337dcade23681c4b3ae638d04094a40a5c21e81f8aac127bfa547dd8d07e7dac1adda539299ab62c3883d15d84a692942da2a1b69eed7946035
|
data/.buildkite/pipeline.yml
CHANGED
|
@@ -1,36 +1,94 @@
|
|
|
1
1
|
steps:
|
|
2
|
-
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
- ruby
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
- group: ":linux: Linux"
|
|
3
|
+
key: linux
|
|
4
|
+
steps:
|
|
5
|
+
- label: ":ruby: Ruby 4.0"
|
|
6
|
+
image: "ruby:4.0"
|
|
7
|
+
commands:
|
|
8
|
+
- ruby -v
|
|
9
|
+
- bundle install
|
|
10
|
+
- bundle exec rake ci
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
- label: ":ruby: Ruby 4.0 +YJIT"
|
|
13
|
+
image: "ruby:4.0"
|
|
14
|
+
env:
|
|
15
|
+
RUBY_YJIT_ENABLE: "1"
|
|
16
|
+
commands:
|
|
17
|
+
- ruby -v
|
|
18
|
+
- bundle install
|
|
19
|
+
- bundle exec rake ci
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
- label: ":ruby: Ruby head"
|
|
22
|
+
soft_fail: true
|
|
23
|
+
image: "rubylang/ruby:master-dev"
|
|
24
|
+
commands:
|
|
25
|
+
- apt-get update && apt-get install -y libyaml-dev
|
|
26
|
+
- ruby -v
|
|
27
|
+
- bundle install
|
|
28
|
+
- bundle exec rake ci
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
- label: ":ruby: Ruby head +YJIT"
|
|
31
|
+
soft_fail: true
|
|
32
|
+
image: "rubylang/ruby:master-dev"
|
|
33
|
+
env:
|
|
34
|
+
RUBY_YJIT_ENABLE: "1"
|
|
35
|
+
commands:
|
|
36
|
+
- apt-get update && apt-get install -y libyaml-dev
|
|
37
|
+
- ruby -v
|
|
38
|
+
- bundle install
|
|
39
|
+
- bundle exec rake ci
|
|
40
|
+
|
|
41
|
+
- group: ":mac: macOS"
|
|
42
|
+
key: macos
|
|
43
|
+
steps:
|
|
44
|
+
- label: ":ruby: Ruby 4.0"
|
|
45
|
+
agents:
|
|
46
|
+
queue: macos
|
|
47
|
+
commands:
|
|
48
|
+
- brew install --quiet ruby@4.0
|
|
49
|
+
- export PATH="$(brew --prefix ruby@4.0)/bin:$PATH"
|
|
50
|
+
- bundle config set --local path .bundle
|
|
51
|
+
- ruby -v
|
|
52
|
+
- bundle install
|
|
53
|
+
- bundle exec rake ci
|
|
54
|
+
|
|
55
|
+
- label: ":ruby: Ruby 4.0 +YJIT"
|
|
56
|
+
agents:
|
|
57
|
+
queue: macos
|
|
58
|
+
env:
|
|
59
|
+
RUBY_YJIT_ENABLE: "1"
|
|
60
|
+
commands:
|
|
61
|
+
- brew install --quiet ruby@4.0
|
|
62
|
+
- export PATH="$(brew --prefix ruby@4.0)/bin:$PATH"
|
|
63
|
+
- bundle config set --local path .bundle
|
|
64
|
+
- ruby -v
|
|
65
|
+
- bundle install
|
|
66
|
+
- bundle exec rake ci
|
|
67
|
+
|
|
68
|
+
- label: ":ruby: Ruby head"
|
|
69
|
+
soft_fail: true
|
|
70
|
+
agents:
|
|
71
|
+
queue: macos
|
|
72
|
+
commands:
|
|
73
|
+
- brew unlink ruby
|
|
74
|
+
- brew install --HEAD --quiet ruby
|
|
75
|
+
- export PATH="$(brew --prefix ruby)/bin:$PATH"
|
|
76
|
+
- bundle config set --local path .bundle
|
|
77
|
+
- ruby -v
|
|
78
|
+
- bundle install
|
|
79
|
+
- bundle exec rake ci
|
|
80
|
+
|
|
81
|
+
- label: ":ruby: Ruby head +YJIT"
|
|
82
|
+
soft_fail: true
|
|
83
|
+
agents:
|
|
84
|
+
queue: macos
|
|
85
|
+
env:
|
|
86
|
+
RUBY_YJIT_ENABLE: "1"
|
|
87
|
+
commands:
|
|
88
|
+
- brew unlink ruby
|
|
89
|
+
- brew install --HEAD --quiet ruby
|
|
90
|
+
- export PATH="$(brew --prefix ruby)/bin:$PATH"
|
|
91
|
+
- bundle config set --local path .bundle
|
|
92
|
+
- ruby -v
|
|
93
|
+
- bundle install
|
|
94
|
+
- bundle exec rake ci
|
data/.dockerignore
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.9.0] - 2026-07-07
|
|
4
|
+
|
|
5
|
+
- Reuse a per-thread response buffer for status lines and headers
|
|
6
|
+
- Pin each worker to a distinct CPU when workers fit 1:1
|
|
7
|
+
- Batch response header and body writes into a single `writev(2)` syscall
|
|
8
|
+
- Close the binder as the last step of graceful shutdown
|
|
9
|
+
- Lower the backpressure floor for tighter load balancing on small pools
|
|
10
|
+
- Add load-aware `SO_REUSEPORT` routing on Linux via an attached BPF program
|
|
11
|
+
- Reuse per-thread read buffers across HTTP/1.1 requests
|
|
12
|
+
- Preserve the first `--bind` when it equals the default
|
|
13
|
+
|
|
14
|
+
## [0.8.0] - 2026-07-02
|
|
15
|
+
|
|
16
|
+
- Add systemd `LISTEN_FDS` socket activation and `sd_notify` lifecycle messages
|
|
17
|
+
- Add hot restart on `SIGUSR2`, inheriting listening sockets across the re-exec
|
|
18
|
+
- Drop `SIGUSR1` stats logging and move phased restart from `SIGUSR2` to `SIGUSR1`
|
|
19
|
+
- Add `chdir` and `environment` for Rack app loading, with fallback to `RAILS_ENV` and `RACK_ENV`
|
|
20
|
+
- Add `access_log_file` for Common Log Format access logging, reopened on `SIGHUP`
|
|
21
|
+
- Add `stdout_file` and `stderr_file` for redirecting stdout/stderr, reopened on `SIGHUP`
|
|
22
|
+
- Add `drain_accept_queue` for dispatching every queued connection on shutdown
|
|
23
|
+
- Add `worker_drain_timeout` for force-killing hung app threads during worker shutdown
|
|
24
|
+
- Reject `Content-Length` values containing non-digit characters with 400
|
|
25
|
+
- Populate `SERVER_SOFTWARE` and `HTTP_VERSION` in the Rack env
|
|
26
|
+
- Honour `X-Forwarded-Proto`, `X-Forwarded-Scheme`, and `X-Forwarded-Ssl` from upstream proxies
|
|
27
|
+
- Split newline-joined response header values into separate header lines
|
|
28
|
+
- Reject excessive chunked framing overhead with 400 (slow-trickle attack guard)
|
|
29
|
+
- Reject ambiguous request framing (`Transfer-Encoding` + `Content-Length`, or `chunked` not the final encoding) with 400
|
|
30
|
+
- Send `100 Continue` when an HTTP/1.1 client sends `Expect: 100-continue`
|
|
31
|
+
- Add new configuration options and split `client:` into protocol-scoped namespaces
|
|
32
|
+
|
|
3
33
|
## [0.7.0] - 2026-06-12
|
|
4
34
|
|
|
5
35
|
- Eagerly consume back-to-back HTTP/2 frame batches in the pipeline collector
|
data/Dockerfile
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
FROM golang:bookworm AS hey-builder
|
|
2
|
+
RUN CGO_ENABLED=0 go install github.com/rakyll/hey@latest
|
|
3
|
+
|
|
4
|
+
FROM ruby:latest
|
|
5
|
+
|
|
6
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
7
|
+
ENV LANG=C.UTF-8
|
|
8
|
+
ENV LC_ALL=C.UTF-8
|
|
9
|
+
ENV RUBY_YJIT_ENABLE=1
|
|
10
|
+
|
|
11
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
12
|
+
clang \
|
|
13
|
+
libbpf-dev \
|
|
14
|
+
libelf-dev \
|
|
15
|
+
linux-libc-dev \
|
|
16
|
+
nghttp2 \
|
|
17
|
+
openssl \
|
|
18
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
19
|
+
|
|
20
|
+
COPY --from=hey-builder /go/bin/hey /usr/local/bin/hey
|
|
21
|
+
|
|
22
|
+
ENV BUNDLE_PATH=/workspace/.bundle
|
|
23
|
+
ENV BUNDLE_APP_CONFIG=/workspace/.bundle
|
|
24
|
+
ENV PATH=/workspace/bin:${PATH}
|
|
25
|
+
|
|
26
|
+
WORKDIR /workspace
|
|
27
|
+
|
|
28
|
+
CMD ["bash"]
|
data/README.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# Raptor
|
|
2
2
|
|
|
3
|
-
Raptor is a high-performance, preloading,
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Raptor is a high-performance, preloading, pre-forking, multi-threaded Ruby 4+ web server implementing Rack 3.2+, using
|
|
4
|
+
NIO for non-blocking I/O and Ractors for parallel HTTP/1.1 and HTTP/2 parsing via native C extensions, which also
|
|
5
|
+
implement HPACK compression.
|
|
6
|
+
|
|
7
|
+
> [!NOTE]
|
|
8
|
+
> **Your application does not need to be Ractor-safe.** Ractors handle protocol-level work only; your Rack application
|
|
9
|
+
> is invoked on a thread pool, so any thread-safe Rack app (including Rails) works as-is.
|
|
10
|
+
|
|
11
|
+
Reference documentation is published at <https://joshuay03.github.io/raptor>.
|
|
6
12
|
|
|
7
13
|
## Installation
|
|
8
14
|
|
|
@@ -30,22 +36,23 @@ run proc { |_env| [200, { "content-type" => "text/plain" }, ["Hello, World!"]] }
|
|
|
30
36
|
|
|
31
37
|
```
|
|
32
38
|
> bundle exec raptor -w 4 -t 3 hello_world.ru
|
|
33
|
-
[Raptor
|
|
34
|
-
[Raptor
|
|
35
|
-
[Raptor
|
|
36
|
-
[Raptor
|
|
37
|
-
[Raptor
|
|
38
|
-
[Raptor
|
|
39
|
-
[Raptor
|
|
40
|
-
[Raptor
|
|
41
|
-
[Raptor
|
|
42
|
-
[Raptor
|
|
43
|
-
[Raptor
|
|
44
|
-
[Raptor
|
|
45
|
-
[Raptor
|
|
46
|
-
[Raptor
|
|
47
|
-
[Raptor
|
|
48
|
-
[Raptor
|
|
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
|
|
49
56
|
```
|
|
50
57
|
|
|
51
58
|
```
|
|
@@ -60,18 +67,139 @@ Also works with `rackup` and `rails server`:
|
|
|
60
67
|
> bundle exec rails server -u raptor
|
|
61
68
|
```
|
|
62
69
|
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
Raptor accepts configuration via command-line flags, a Ruby config file, or both (CLI flags override config file
|
|
73
|
+
values). Run `bundle exec raptor --help` for the full flag list.
|
|
74
|
+
|
|
75
|
+
The config file is a Ruby file that evaluates to a hash of options. By default Raptor loads `raptor.rb` then
|
|
76
|
+
`config/raptor.rb` from the working directory; pass `-c PATH` to point at a specific file. Settings are nested under
|
|
77
|
+
`connection:` (shared across protocols), `http1:` (HTTP/1.1-specific), and `http2:` (HTTP/2-specific).
|
|
78
|
+
|
|
79
|
+
```ruby
|
|
80
|
+
# raptor.rb
|
|
81
|
+
|
|
82
|
+
{
|
|
83
|
+
binds: ["tcp://0.0.0.0:9292"],
|
|
84
|
+
socket_backlog: 1024,
|
|
85
|
+
drain_accept_queue: false,
|
|
86
|
+
workers: 4,
|
|
87
|
+
ractors: 1,
|
|
88
|
+
threads: 3,
|
|
89
|
+
chdir: nil,
|
|
90
|
+
environment: nil,
|
|
91
|
+
connection: {
|
|
92
|
+
first_data_timeout: 30,
|
|
93
|
+
chunk_data_timeout: 10,
|
|
94
|
+
write_timeout: 5,
|
|
95
|
+
max_body_size: nil,
|
|
96
|
+
body_spool_threshold: 1024 * 1024,
|
|
97
|
+
},
|
|
98
|
+
http1: {
|
|
99
|
+
persistent_data_timeout: 65,
|
|
100
|
+
max_keepalive_requests: 100,
|
|
101
|
+
},
|
|
102
|
+
http2: {
|
|
103
|
+
max_concurrent_streams: 100,
|
|
104
|
+
},
|
|
105
|
+
worker_boot_timeout: 60,
|
|
106
|
+
worker_timeout: 60,
|
|
107
|
+
worker_drain_timeout: 25,
|
|
108
|
+
worker_shutdown_timeout: 30,
|
|
109
|
+
stats_file: "tmp/raptor.json",
|
|
110
|
+
pid_file: nil,
|
|
111
|
+
stdout_file: nil,
|
|
112
|
+
stderr_file: nil,
|
|
113
|
+
access_log_file: nil,
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Bindings
|
|
118
|
+
|
|
119
|
+
Raptor accepts multiple `binds:` URIs across three schemes.
|
|
120
|
+
|
|
121
|
+
- `tcp://host:port` for TCP. Host can be a specific IP, `0.0.0.0` / `[::]`, or `localhost` (expanded to both IPv4 and
|
|
122
|
+
IPv6 loopback addresses).
|
|
123
|
+
- `unix:///path/to/socket` for a Unix domain socket. Stale sockets left by crashed processes are cleaned up
|
|
124
|
+
automatically.
|
|
125
|
+
- `ssl://host:port?cert=/path/to.crt&key=/path/to.key` for TLS. HTTP/1.1 and HTTP/2 are negotiated via ALPN.
|
|
126
|
+
|
|
127
|
+
Multiple binds can be combined freely.
|
|
128
|
+
|
|
129
|
+
## Signals
|
|
130
|
+
|
|
131
|
+
Send to the master process.
|
|
132
|
+
|
|
133
|
+
| Signal | Effect |
|
|
134
|
+
| ------ | ----------------------------------------------------------- |
|
|
135
|
+
| `INT` | Graceful shutdown |
|
|
136
|
+
| `TERM` | Graceful shutdown |
|
|
137
|
+
| `HUP` | Reopen `stdout_file`, `stderr_file`, and `access_log_file` |
|
|
138
|
+
| `USR1` | Phased restart (rolling worker replacement) |
|
|
139
|
+
| `USR2` | Hot restart (re-exec master, inheriting listening sockets) |
|
|
140
|
+
|
|
141
|
+
## Restarts
|
|
142
|
+
|
|
143
|
+
- **Phased restart** (`USR1`) replaces workers one at a time, waiting for each new worker to boot before retiring the
|
|
144
|
+
previous one. The master process keeps running, so existing workers continue serving until they are individually
|
|
145
|
+
replaced. Use to pick up code changes that don't affect the master's boot path.
|
|
146
|
+
- **Hot restart** (`USR2`) re-execs the master process with its original command line, inheriting the listening sockets
|
|
147
|
+
so accepted connections continue to be served across the swap. The successor master re-runs initialization from
|
|
148
|
+
scratch. Use to pick up changes that affect master-level state (config layout, dependency upgrades, Raptor itself).
|
|
149
|
+
|
|
150
|
+
## systemd
|
|
151
|
+
|
|
152
|
+
Raptor implements socket activation (`LISTEN_FDS`) and `sd_notify`, so it integrates cleanly with `Type=notify` units.
|
|
153
|
+
When the socket unit is active, systemd hands the pre-bound listening file descriptors to Raptor, which serves them in
|
|
154
|
+
place of `binds:`. `READY=1`, `STOPPING=1`, and `RELOADING=1` lifecycle messages are emitted automatically.
|
|
155
|
+
|
|
156
|
+
```ini
|
|
157
|
+
# /etc/systemd/system/myapp.socket
|
|
158
|
+
[Socket]
|
|
159
|
+
ListenStream=0.0.0.0:9292
|
|
160
|
+
|
|
161
|
+
[Install]
|
|
162
|
+
WantedBy=sockets.target
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
```ini
|
|
166
|
+
# /etc/systemd/system/myapp.service
|
|
167
|
+
[Service]
|
|
168
|
+
Type=notify
|
|
169
|
+
WorkingDirectory=/srv/myapp
|
|
170
|
+
ExecStart=/usr/bin/bundle exec raptor
|
|
171
|
+
ExecReload=/bin/kill -USR2 $MAINPID
|
|
172
|
+
KillMode=mixed
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Stats
|
|
176
|
+
|
|
177
|
+
Each worker writes per-worker stats (request count, busy threads, backlog, last check-in) to shared memory and to a
|
|
178
|
+
JSON file (default `tmp/raptor.json`; set via `stats_file`).
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
> bundle exec raptor stats
|
|
182
|
+
Master PID: 91348
|
|
183
|
+
Worker 0 (phase 0): pid=91350, requests=1234, busy=2/3, backlog=0, booted, last_checkin=10:42:01
|
|
184
|
+
Worker 1 (phase 0): pid=91351, requests=1199, busy=1/3, backlog=0, booted, last_checkin=10:42:01
|
|
185
|
+
...
|
|
186
|
+
```
|
|
187
|
+
|
|
63
188
|
## (Micro) Benchmarks
|
|
64
189
|
|
|
65
|
-
Raptor 0.
|
|
190
|
+
Raptor 0.9.0 vs Puma 8.0.2, median of 3 runs across two workload profiles: IO-bound (sleep for a random 5-50ms then return small JSON) and CPU-bound (serialise a JSON array of 20-200 items).
|
|
66
191
|
|
|
67
|
-
| Protocol | Raptor | Puma
|
|
68
|
-
| --------------------- | ----------- | ----------- |
|
|
69
|
-
| HTTP/1.1 |
|
|
70
|
-
| HTTP/1.1
|
|
71
|
-
| HTTP/
|
|
192
|
+
| Protocol | Workload | Raptor | Puma | +/- vs Puma |
|
|
193
|
+
| --------------------- | -------- | ----------- | ---------- | ----------- |
|
|
194
|
+
| HTTP/1.1 | IO | 0.4k req/s | 0.4k req/s | +3.4% |
|
|
195
|
+
| HTTP/1.1 | CPU | 11.5k req/s | 9k req/s | +27.6% |
|
|
196
|
+
| HTTP/1.1 (keep-alive) | IO | 0.4k req/s | 0.4k req/s | +1.5% |
|
|
197
|
+
| HTTP/1.1 (keep-alive) | CPU | 28.8k req/s | 26k req/s | +10.9% |
|
|
198
|
+
| HTTP/2 | IO | 0.3k req/s | N/A | - |
|
|
199
|
+
| HTTP/2 | CPU | 29.6k req/s | N/A | - |
|
|
72
200
|
|
|
73
|
-
> ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +YJIT +PRISM [
|
|
74
|
-
> 4 workers, 3 threads,
|
|
201
|
+
> ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +YJIT +PRISM [aarch64-linux]
|
|
202
|
+
> 4 workers, 3 threads, 24 concurrent connections
|
|
75
203
|
|
|
76
204
|
See [bin/benchmark](bin/benchmark) for more details.
|
|
77
205
|
|
|
@@ -81,6 +209,10 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
|
81
209
|
extensions and run the tests. You can also run `bin/console` for an interactive prompt that will allow you to
|
|
82
210
|
experiment.
|
|
83
211
|
|
|
212
|
+
On macOS (or any non-Linux host), `bin/dev` builds and drops you into a Docker image with Ruby and the required Linux
|
|
213
|
+
toolchain preinstalled, mounting the repo at `/workspace`. Run `bin/dev` for an interactive shell, or
|
|
214
|
+
`bin/dev <command>` for one-off commands like `bin/dev bundle exec rake` or `bin/dev bin/benchmark`.
|
|
215
|
+
|
|
84
216
|
## Contributing
|
|
85
217
|
|
|
86
218
|
Bug reports and pull requests are welcome on GitHub at https://github.com/joshuay03/raptor. This project is intended to
|
data/Rakefile
CHANGED
|
@@ -16,6 +16,24 @@ Rake::ExtensionTask.new("raptor_http2", GEMSPEC) do |ext|
|
|
|
16
16
|
ext.lib_dir = "lib/raptor"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
Rake::ExtensionTask.new("raptor_native", GEMSPEC) do |ext|
|
|
20
|
+
ext.lib_dir = "lib/raptor"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
namespace :bpf do
|
|
24
|
+
task :compile do
|
|
25
|
+
if RUBY_PLATFORM.include?("linux")
|
|
26
|
+
arch = `uname -m`.chomp
|
|
27
|
+
Dir["ext/raptor_bpf/*.bpf.c"].each do |source|
|
|
28
|
+
object = source.sub(/\.c\z/, ".o")
|
|
29
|
+
sh "clang -O2 -g -target bpf -I/usr/include/#{arch}-linux-gnu -c #{source} -o #{object}"
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
puts "Skipping bpf:compile on #{RUBY_PLATFORM}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
19
37
|
namespace :rbs do
|
|
20
38
|
task :generate do
|
|
21
39
|
puts
|
|
@@ -23,6 +41,6 @@ namespace :rbs do
|
|
|
23
41
|
end
|
|
24
42
|
end
|
|
25
43
|
|
|
26
|
-
task default: %i[clobber compile rbs:generate test]
|
|
44
|
+
task default: %i[clobber compile bpf:compile rbs:generate test]
|
|
27
45
|
task build: %i[clobber compile rbs:generate]
|
|
28
46
|
task ci: %i[clobber compile test]
|