solid-resp-ractor 0.1.3 → 0.1.4
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 +12 -0
- data/README.md +83 -0
- data/lib/solid_resp_ractor/source.rb +6 -1
- data/lib/solid_resp_ractor/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e95465d9cdecff50ce715e8150335b5f90da49121a1a047edb433210e308015c
|
|
4
|
+
data.tar.gz: 1dd82d1a8d80ea412d1ce2257f51b081dc5231718f9aaed71386d739a6bc8ac3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bd9661ccd7e481088936f7b3425da4bacf8a58754dab3122397bbd003d03c7704fe1e6b813be11575dab60b790548c776ca1e452998c80891b8a967c4ccfa7d2
|
|
7
|
+
data.tar.gz: 901b266a995302514ebe6f0fb4cdfd0e9641e415b908fb109b249b8ed14e0b0f2fe2572c2e902158d6af9918f50cc1ed725f1a48f1c70c825484578dbbc99a4b
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.1.4] - 2026-10-01
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Reuse a destination String for non-blocking IO reads instead of allocating a
|
|
10
|
+
chunk-sized String for every socket response.
|
|
11
|
+
- Reduce loopback GET allocation from 16,609.8 to 120.8 bytes per operation
|
|
12
|
+
and from 6.0 to 4.0 objects per operation in the Ruby 4.0.1 benchmark.
|
|
13
|
+
- Improve loopback GET throughput by 8.18% at eight Ractors while preserving
|
|
14
|
+
Reader parser-buffer invariants.
|
|
15
|
+
|
|
5
16
|
## [0.1.3] - 2026-09-30
|
|
6
17
|
|
|
7
18
|
### Changed
|
|
@@ -50,6 +61,7 @@ All notable changes to this project are documented in this file.
|
|
|
50
61
|
input, and parallel Ractors.
|
|
51
62
|
- Ractor-shareable default encoder with no global mutable state.
|
|
52
63
|
|
|
64
|
+
[0.1.4]: https://github.com/nicolasva/solid-resp-ractor/compare/v0.1.3...v0.1.4
|
|
53
65
|
[0.1.3]: https://github.com/nicolasva/solid-resp-ractor/compare/v0.1.2...v0.1.3
|
|
54
66
|
[0.1.2]: https://github.com/nicolasva/solid-resp-ractor/compare/v0.1.1...v0.1.2
|
|
55
67
|
[0.1.1]: https://github.com/nicolasva/solid-resp-ractor/compare/v0.1.0...v0.1.1
|
data/README.md
CHANGED
|
@@ -272,6 +272,89 @@ after at least 16 KiB have been consumed and that prefix occupies at least half
|
|
|
272
272
|
of the buffer. This avoids copying a large unread suffix after small fragmented
|
|
273
273
|
reads while still releasing consumed data during long-lived streams.
|
|
274
274
|
|
|
275
|
+
## Reader benchmark
|
|
276
|
+
|
|
277
|
+
Encoding, Reader-only, TCP, allocation, and Ractor-scaling benchmarks live in
|
|
278
|
+
the separate `benchmark_solid_resp_ractor` sibling bundle so benchmark tooling
|
|
279
|
+
and generated reports remain outside the gem.
|
|
280
|
+
|
|
281
|
+
Run the complete matrix from the sibling checkout:
|
|
282
|
+
|
|
283
|
+
```sh
|
|
284
|
+
cd ../benchmark_solid_resp_ractor
|
|
285
|
+
RBENV_VERSION=4.0.1 \
|
|
286
|
+
BENCHMARK_OUTPUT=results/ruby-4.0.1-reader.md \
|
|
287
|
+
bundle exec rake
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Current baseline
|
|
291
|
+
|
|
292
|
+
**Environment:** Ruby 4.0.1 (arm64-darwin25); solid-resp-ractor 0.1.3;
|
|
293
|
+
Redis 8.10.0. Values are medians of three runs with one second of warmup and
|
|
294
|
+
three seconds of measurement per row. Pipeline metrics are amortized per
|
|
295
|
+
command. Reader-only rows consume an in-memory repeating 16 KiB source.
|
|
296
|
+
Reader + TCP rows use an isolated loopback Redis server. Allocation metrics
|
|
297
|
+
are measured separately in one Ractor with GC disabled, then repeated across
|
|
298
|
+
the scaling rows; Redis allocations are excluded.
|
|
299
|
+
|
|
300
|
+
| Ractors | Layer | Operation | ops/s | Scaling efficiency | alloc/op | bytes/op |
|
|
301
|
+
|---:|---|---|---:|---:|---:|---:|
|
|
302
|
+
| 1 | Encode | GET | 1,261,840 | 100.0% | 2.0 | 104.8 |
|
|
303
|
+
| 2 | Encode | GET | 2,298,471 | 91.1% | 2.0 | 104.8 |
|
|
304
|
+
| 4 | Encode | GET | 3,898,679 | 77.2% | 2.0 | 104.8 |
|
|
305
|
+
| 8 | Encode | GET | 5,234,281 | 51.9% | 2.0 | 104.8 |
|
|
306
|
+
| 1 | Encode | SET | 974,781 | 100.0% | 2.0 | 104.8 |
|
|
307
|
+
| 2 | Encode | SET | 1,797,823 | 92.2% | 2.0 | 104.8 |
|
|
308
|
+
| 4 | Encode | SET | 3,249,650 | 83.3% | 2.0 | 104.8 |
|
|
309
|
+
| 8 | Encode | SET | 4,470,244 | 57.3% | 2.0 | 104.8 |
|
|
310
|
+
| 1 | Encode | pipeline 50 | 1,345,762 | 100.0% | 2.0 | 145.8 |
|
|
311
|
+
| 2 | Encode | pipeline 50 | 2,482,408 | 92.2% | 2.0 | 145.8 |
|
|
312
|
+
| 4 | Encode | pipeline 50 | 4,250,421 | 79.0% | 2.0 | 145.8 |
|
|
313
|
+
| 8 | Encode | pipeline 50 | 5,779,732 | 53.7% | 2.0 | 145.8 |
|
|
314
|
+
| 1 | Reader | +OK | 1,690,247 | 100.0% | 2.0 | 40.8 |
|
|
315
|
+
| 2 | Reader | +OK | 3,197,883 | 94.6% | 2.0 | 40.8 |
|
|
316
|
+
| 4 | Reader | +OK | 5,788,420 | 85.6% | 2.0 | 40.8 |
|
|
317
|
+
| 8 | Reader | +OK | 8,029,110 | 59.4% | 2.0 | 40.8 |
|
|
318
|
+
| 1 | Reader | integer | 1,562,655 | 100.0% | 2.0 | 40.8 |
|
|
319
|
+
| 2 | Reader | integer | 2,968,526 | 95.0% | 2.0 | 40.8 |
|
|
320
|
+
| 4 | Reader | integer | 5,459,562 | 87.3% | 2.0 | 40.8 |
|
|
321
|
+
| 8 | Reader | integer | 7,423,102 | 59.4% | 2.0 | 40.8 |
|
|
322
|
+
| 1 | Reader | bulk 16 B | 787,426 | 100.0% | 3.0 | 120.8 |
|
|
323
|
+
| 2 | Reader | bulk 16 B | 1,533,310 | 97.4% | 3.0 | 120.8 |
|
|
324
|
+
| 4 | Reader | bulk 16 B | 2,796,102 | 88.8% | 3.0 | 120.8 |
|
|
325
|
+
| 8 | Reader | bulk 16 B | 4,090,043 | 64.9% | 3.0 | 120.8 |
|
|
326
|
+
| 1 | Reader | bulk 1 KiB | 709,062 | 100.0% | 3.0 | 1,105.8 |
|
|
327
|
+
| 2 | Reader | bulk 1 KiB | 1,225,199 | 86.4% | 3.0 | 1,105.8 |
|
|
328
|
+
| 4 | Reader | bulk 1 KiB | 2,055,006 | 72.5% | 3.0 | 1,105.8 |
|
|
329
|
+
| 8 | Reader | bulk 1 KiB | 2,597,586 | 45.8% | 3.0 | 1,105.8 |
|
|
330
|
+
| 1 | Reader | array 50 | 32,877 | 100.0% | 103.0 | 2,680.8 |
|
|
331
|
+
| 2 | Reader | array 50 | 60,955 | 92.7% | 103.0 | 2,680.8 |
|
|
332
|
+
| 4 | Reader | array 50 | 115,104 | 87.5% | 103.0 | 2,680.8 |
|
|
333
|
+
| 8 | Reader | array 50 | 185,791 | 70.6% | 103.0 | 2,680.8 |
|
|
334
|
+
| 1 | Reader | nested RESP3 | 87,279 | 100.0% | 34.0 | 1,080.9 |
|
|
335
|
+
| 2 | Reader | nested RESP3 | 166,456 | 95.4% | 34.0 | 1,080.9 |
|
|
336
|
+
| 4 | Reader | nested RESP3 | 302,211 | 86.6% | 34.0 | 1,080.9 |
|
|
337
|
+
| 8 | Reader | nested RESP3 | 433,100 | 62.0% | 34.0 | 1,080.9 |
|
|
338
|
+
| 1 | Reader + TCP | GET | 40,173 | 100.0% | 4.0 | 120.8 |
|
|
339
|
+
| 2 | Reader + TCP | GET | 66,235 | 82.4% | 4.0 | 120.8 |
|
|
340
|
+
| 4 | Reader + TCP | GET | 89,146 | 55.5% | 4.0 | 120.8 |
|
|
341
|
+
| 8 | Reader + TCP | GET | 102,060 | 31.8% | 4.0 | 120.8 |
|
|
342
|
+
| 1 | Reader + TCP | pipeline 50 | 473,123 | 100.0% | 3.0 | 120.0 |
|
|
343
|
+
| 2 | Reader + TCP | pipeline 50 | 878,582 | 92.8% | 3.0 | 120.0 |
|
|
344
|
+
| 4 | Reader + TCP | pipeline 50 | 1,478,781 | 78.1% | 3.0 | 120.0 |
|
|
345
|
+
| 8 | Reader + TCP | pipeline 50 | 2,044,122 | 54.0% | 3.0 | 120.0 |
|
|
346
|
+
|
|
347
|
+
Pure bulk decoding represents roughly 5.1% of the service time of a
|
|
348
|
+
non-pipelined loopback GET, but about 60% of an amortized pipeline command.
|
|
349
|
+
These are directional ratios rather than profiler attribution.
|
|
350
|
+
|
|
351
|
+
Reusing the destination String passed to `read_nonblock` reduced GET
|
|
352
|
+
allocation from 16,609.8 to 120.8 bytes/op (-99.27%) and from 6.0 to 4.0
|
|
353
|
+
objects/op. GET throughput changed by -0.68% at 1R and improved by 8.18% at
|
|
354
|
+
8R. Pipeline allocation fell from 472.3 to 120.0 bytes/op (-74.59%), while
|
|
355
|
+
throughput improved by 2.23% at 8R. The allocation improvement is structural
|
|
356
|
+
and does not require changing Reader parser invariants.
|
|
357
|
+
|
|
275
358
|
## Development
|
|
276
359
|
|
|
277
360
|
```sh
|
|
@@ -47,6 +47,7 @@ module SolidRespRactor
|
|
|
47
47
|
|
|
48
48
|
@selector = selector
|
|
49
49
|
@clock = clock
|
|
50
|
+
@read_buffer = +""
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
def read(timeout:)
|
|
@@ -54,7 +55,11 @@ module SolidRespRactor
|
|
|
54
55
|
|
|
55
56
|
deadline = nil
|
|
56
57
|
loop do
|
|
57
|
-
chunk = @io.read_nonblock(
|
|
58
|
+
chunk = @io.read_nonblock(
|
|
59
|
+
@chunk_size,
|
|
60
|
+
@read_buffer,
|
|
61
|
+
exception: false,
|
|
62
|
+
)
|
|
58
63
|
return chunk unless chunk == :wait_readable || chunk == :wait_writable
|
|
59
64
|
|
|
60
65
|
deadline ||= @clock.now + timeout if timeout
|