cztop 1.3.1 → 2.0.0.rc1

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +99 -0
  3. data/CLAUDE.md +39 -0
  4. data/Gemfile +0 -4
  5. data/README.md +90 -179
  6. data/ZGUIDE_SUMMARY.md +1111 -0
  7. data/cztop.gemspec +6 -7
  8. data/lib/cztop/curve/auth.rb +100 -0
  9. data/lib/cztop/curve.rb +126 -0
  10. data/lib/cztop/ffi.rb +489 -0
  11. data/lib/cztop/has_ffi_delegate.rb +20 -9
  12. data/lib/cztop/monitor.rb +88 -87
  13. data/lib/cztop/socket/dealer.rb +28 -0
  14. data/lib/cztop/socket/fd_wait.rb +88 -0
  15. data/lib/cztop/socket/pair.rb +28 -0
  16. data/lib/cztop/socket/pub.rb +27 -0
  17. data/lib/cztop/socket/pull.rb +27 -0
  18. data/lib/cztop/socket/push.rb +27 -0
  19. data/lib/cztop/socket/readable.rb +76 -0
  20. data/lib/cztop/socket/rep.rb +28 -0
  21. data/lib/cztop/socket/req.rb +28 -0
  22. data/lib/cztop/socket/router.rb +38 -0
  23. data/lib/cztop/socket/stream.rb +29 -0
  24. data/lib/cztop/socket/sub.rb +50 -0
  25. data/lib/cztop/socket/types.rb +2 -341
  26. data/lib/cztop/socket/writable.rb +86 -0
  27. data/lib/cztop/socket/xpub.rb +28 -0
  28. data/lib/cztop/socket/xsub.rb +28 -0
  29. data/lib/cztop/socket.rb +94 -27
  30. data/lib/cztop/version.rb +1 -1
  31. data/lib/cztop/zsock_options.rb +333 -364
  32. data/lib/cztop.rb +28 -48
  33. metadata +32 -55
  34. data/lib/cztop/actor.rb +0 -340
  35. data/lib/cztop/authenticator.rb +0 -113
  36. data/lib/cztop/beacon.rb +0 -117
  37. data/lib/cztop/cert_store.rb +0 -65
  38. data/lib/cztop/certificate.rb +0 -234
  39. data/lib/cztop/config/comments.rb +0 -77
  40. data/lib/cztop/config/serialization.rb +0 -102
  41. data/lib/cztop/config/traversing.rb +0 -188
  42. data/lib/cztop/config.rb +0 -135
  43. data/lib/cztop/frame.rb +0 -193
  44. data/lib/cztop/message/frames.rb +0 -88
  45. data/lib/cztop/message.rb +0 -220
  46. data/lib/cztop/metadata.rb +0 -111
  47. data/lib/cztop/poller/aggregated.rb +0 -142
  48. data/lib/cztop/poller/zmq.rb +0 -92
  49. data/lib/cztop/poller/zpoller.rb +0 -125
  50. data/lib/cztop/poller.rb +0 -245
  51. data/lib/cztop/polymorphic_zsock_methods.rb +0 -32
  52. data/lib/cztop/proxy.rb +0 -164
  53. data/lib/cztop/send_receive_methods.rb +0 -171
  54. data/lib/cztop/z85/padded.rb +0 -107
  55. data/lib/cztop/z85/pipe.rb +0 -200
  56. data/lib/cztop/z85.rb +0 -90
  57. data/lib/cztop/zap.rb +0 -259
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1347b002694da386afc7249ac227de7ee7f1224bb140564334b20d646336e73a
4
- data.tar.gz: faa02a6ba73af47cbff6af9664562e41d359ba4f13eb5813d6e1e5fc992b6aa8
3
+ metadata.gz: de1d34e78550eaaaa2397a9bc1d1a29a57e36ef00d573a30e68b3903f8e1e43c
4
+ data.tar.gz: a9e4522e743b7dae26358acdcfb003fe12a15d5357654b6e32909c7e7ad5bf34
5
5
  SHA512:
6
- metadata.gz: fd22665b89635d5f5a6bbd8326a1de9c13f77a39a253a07316089d9124ec18dadebc67f86b5ec471cc3e09cb0eb6c32d027ad523573fc2b8e502c37b05119cc2
7
- data.tar.gz: 1de1565a9d4656e9887958befb29ea0cad66ad90f30d84244f3f60bbcc7069a0cfc20bb1be1c8ff06db34e02546ca9ff8349c01689faa1725e6f8cb069e846db
6
+ metadata.gz: b81a176e6020b002abd3425bc66781e5eb7fdf3d907649139ffacfc7e7b1b12a17498e769dbb90fb13c29bbfe8d5d44ef8d73fa4446bb80613f9aaf159ca0eff
7
+ data.tar.gz: ebd44ce64395ddf965682392f7c719bc94fc4ae4277da5340c35b7cd2f9bf8c0206cb92f29fb2350ba6804de244b1c1d3df37d2359c4f391210bfb0e3626688f
data/CHANGES.md CHANGED
@@ -1,3 +1,102 @@
1
+ 2.0.0.rc1
2
+ -----
3
+
4
+ ### Breaking changes
5
+
6
+ * **Removed classes:** Actor, Authenticator, Beacon, Certificate, CertStore, Config,
7
+ Frame, Message, Metadata, Monitor, Poller, Proxy, Z85, ZAP
8
+ * **Removed modules:** SendReceiveMethods, PolymorphicZsockMethods
9
+ * **Removed socket types (draft API dropped):** SERVER, CLIENT, RADIO, DISH,
10
+ GATHER, SCATTER
11
+ * **Removed CURVE/PLAIN/GSSAPI security API:**
12
+ - `Socket#CURVE_server!`, `Socket#CURVE_client!`
13
+ - CURVE option methods (`#CURVE_server?`, `#CURVE_serverkey`,
14
+ `#CURVE_secretkey`, `#CURVE_publickey`, etc.)
15
+ - PLAIN option methods (`#PLAIN_server?`, `#PLAIN_username`,
16
+ `#PLAIN_password`, etc.)
17
+ - `#mechanism`, `#zap_domain`
18
+ * **Send/receive API changed:**
19
+ - `#receive` now returns `Array<String>` (was `CZTop::Message`)
20
+ - `#<<` accepts `String` or `Array<String>` directly (was `Message.coerce`)
21
+ - `#send` is the primary method; `#<<` is an alias (note: `#send` shadows
22
+ `Object#send`; use `__send__` for Ruby dispatch)
23
+ - `SendReceiveMethods` split into `Socket::Readable`, `Socket::Writable`, and
24
+ `Socket::FdWait` mixins; socket types include only what they need
25
+ (e.g. PUB includes only Writable, SUB only Readable)
26
+ * **Time-based options now use seconds** (was milliseconds) — applies to
27
+ `#recv_timeout`, `#send_timeout`, `#linger`, `#heartbeat_ivl`, `#heartbeat_ttl`,
28
+ `#heartbeat_timeout`, `#reconnect_ivl`
29
+ * **Sentinel values changed from -1 to nil:**
30
+ - `#recv_timeout` / `#send_timeout` — returns/accepts `nil` instead
31
+ of `-1` for "no timeout"
32
+ - `#linger` — `nil` instead of `-1` for "wait indefinitely"
33
+ - `#heartbeat_timeout` — `nil` instead of `-1` for "use IVL"
34
+ - `#reconnect_ivl` — `nil` instead of `-1` for "disabled"
35
+ * **`Socket::SUB#initialize` subscription is now a `prefix:` kwarg** — was a
36
+ positional parameter; defaults to `EVERYTHING` (`''`), pass `prefix: nil` to
37
+ skip subscribing
38
+ * **`#set_unbounded` moved from PolymorphicZsockMethods to Socket**
39
+ * **`OptionsAccessor` removed** — all option methods now live directly on
40
+ `Socket` (e.g. `socket.sndhwm` instead of `socket.options.sndhwm`)
41
+ * **`#rcvtimeo` / `#sndtimeo` removed** — use `#recv_timeout` / `#send_timeout`
42
+ (aliased as `#read_timeout` / `#write_timeout`). `nil` = no timeout
43
+ (block forever), `0` = nonblocking, positive = timeout in seconds.
44
+ * **Fuzzy `#[]` / `#[]=` accessors removed**
45
+ * **`czmq-ffi-gen` gem dependency removed** — replaced with handcrafted FFI
46
+ bindings in `lib/cztop/ffi.rb`
47
+ * **Minimum Ruby version raised to 3.3**
48
+
49
+ ### New features
50
+
51
+ * **`CZTop::Monitor`** — socket event monitoring via CZMQ's zmonitor actor;
52
+ detects CONNECTED, LISTENING, ACCEPTED, DISCONNECTED, and other ZMQ events.
53
+ Returns `Monitor::Event` value objects (`Data.define(:name, :endpoint, :peer_address)`)
54
+ * **`Cztop` module alias** — `Cztop = CZTop` for conventional Ruby naming;
55
+ both `Cztop::Socket::REQ` and `CZTop::Socket::REQ` work
56
+ * **`.bind` and `.connect` class methods** on all socket types —
57
+ `REP.bind(endpoint)` and `REQ.connect(endpoint)` as shorthand for
58
+ `new(nil).tap { |s| s.bind(endpoint) }`; passes through `curve:`,
59
+ `prefix:` (SUB), and other kwargs
60
+ * **CURVE encryption** with ergonomic `curve:` kwarg on all socket constructors:
61
+ - `CZTop::CURVE.keypair` — generate keypairs (32-byte binary)
62
+ - `CZTop::CURVE.public_key(secret_key)` — derive public from secret
63
+ - `CZTop::CURVE.z85_encode` / `.z85_decode` — Z85 utility for interop
64
+ - `CZTop::CURVE::Auth` — in-memory ZAP handler (no filesystem, no zauth actor)
65
+ - Server: `CZTop::Socket::REP.new(endpoint, curve: { secret_key: sk })`
66
+ - Client: `CZTop::Socket::REQ.new(endpoint, curve: { secret_key: sk, server_key: pk })`
67
+ * **`@`/`>` endpoint prefix convention** supported on all socket constructors
68
+ (e.g. `PAIR.new("@inproc://ep")` to bind, `PAIR.new(">inproc://ep")` to connect)
69
+ * **New socket options:**
70
+ - `#reconnect_ivl_max` — max reconnect backoff interval (exponential backoff)
71
+ - `#max_msg_size` — max inbound message size (DoS protection)
72
+ - `#immediate?` / `#immediate=` — queue only for completed connections
73
+ - `#conflate?` / `#conflate=` — keep only last message (last-value-cache)
74
+ - `#tcp_keepalive` / `#tcp_keepalive_idle` / `#tcp_keepalive_cnt` /
75
+ `#tcp_keepalive_intvl` — TCP keepalive tuning
76
+
77
+ ### Other changes
78
+
79
+ * **FFI bindings for zactor, zstr, zsock_wait** — foundational bindings for
80
+ CZMQ actor-based APIs (used by Monitor, extensible for future actors)
81
+ * replace old examples with numbered `examples/zguide/` pattern files
82
+ (01–12: req/rep, pub/sub, pipeline, lazy pirate, heartbeat, LVC, clone,
83
+ majordomo, titanic, binary star, freelance)
84
+ * expand ZGUIDE_SUMMARY.md to ~30 min read with working code excerpts,
85
+ threading/concurrency guidance, and common mistakes section
86
+ * replace RSpec with Minitest
87
+ * replace `perf/` with `bench/` using benchmark-ips
88
+ * add per-socket-type integration test files for all 13 types
89
+ * add socket combination tests (ROUTER+REQ, ROUTER+ROUTER, pipeline, XPUB+multi SUB)
90
+ * add HWM mute state tests (PUSH/PULL blocking, PUB/SUB dropping, ROUTER mandatory)
91
+ * add REQ/REP reconnection tests (TCP restart, stuck-state demonstration)
92
+ * add STREAM ↔ raw TCP integration tests
93
+ * add CURVE throughput benchmark (`bench/threads/curve_throughput.rb`)
94
+ * add Shannon entropy system tests for CURVE (`test/system/`)
95
+ * split socket creation from connect/bind to support pre-connect option setting
96
+ * tune FD_TIMEOUT (500ms → 250ms) and JIFFY (15ms → 1ms) for better responsiveness
97
+ * fix zmq_errno race condition in `#raise_zmq_err`
98
+ * move CZMQ signal handler disabling into `lib/cztop/ffi.rb`
99
+
1
100
  1.3.2 (1/3/2025)
2
101
  -----
3
102
  * add 'benchmark' dependency for specs
data/CLAUDE.md ADDED
@@ -0,0 +1,39 @@
1
+ # CZTop
2
+
3
+ Ruby FFI binding for CZMQ/ZMQ. Version 2.0.0.pre1. Requires Ruby >= 3.3.
4
+
5
+ ## Architecture
6
+
7
+ - `lib/cztop/socket.rb` — Socket base class (connect, bind, etc.)
8
+ - `lib/cztop/socket/fd_wait.rb` — `FdWait` mixin: FD polling infrastructure (`FD_TIMEOUT`, `JIFFY`, `#wait_for_fd_signal`, `#wait_for_socket_state`)
9
+ - `lib/cztop/socket/readable.rb` — `Readable` mixin: `#receive` → `Array<String>`, `#wait_readable`, `#read_timeout`
10
+ - `lib/cztop/socket/writable.rb` — `Writable` mixin: `#send` accepts `String`/`Array<String>`, `#<<`, `#wait_writable`, `#write_timeout`
11
+ - `lib/cztop/socket/types.rb` — `Types` constants + `TypeNames`
12
+ - `lib/cztop/socket/{req,rep,dealer,router,pub,sub,xpub,xsub,push,pull,pair,stream}.rb` — individual socket types
13
+ - `lib/cztop/ffi.rb` — FFI bindings (zsock, zmsg, zframe, zstr) + CZMQ signal handler disabling
14
+ - `bench/` — benchmark-ips scripts (async/threads × throughput/latency)
15
+
16
+ ### ZMQ FD polling
17
+
18
+ ZMQ uses a single edge-triggered FD for both read/write signaling. `#wait_for_socket_state`
19
+ checks socket readiness first (fast path via `#readable?`/`#writable?`), then polls the FD.
20
+
21
+ - `FD_TIMEOUT` (250ms) — max time in `IO#wait_readable` per loop iteration; safety net for missed edges
22
+ - `JIFFY` (1ms) — sleep after false wakeup (FD signals but socket not ready)
23
+ - Edge misses are rare (~0.2% of calls in ipc/tcp req/rep), never in inproc throughput
24
+ - `IO#wait_readable` is interruptible by signals — Ctrl-C works immediately
25
+ - `__send__` used instead of `send` to avoid clash with ZMQ `#send` method
26
+ - Socket types include only the mixins they need (e.g. PUB includes only Writable, SUB only Readable)
27
+
28
+ ### Tuning rationale
29
+
30
+ - JIFFY 15ms→1ms: each edge miss stalls for full JIFFY duration; 1ms reduces impact 15x
31
+ - FD_TIMEOUT 500ms→250ms: halves worst-case stall; no measurable perf impact since FD signals correctly 99.8% of the time
32
+ - Measured with `bench/jiffy_sweep.rb`, `bench/fd_timeout_sweep.rb`, `bench/edge_miss_count.rb`
33
+
34
+ ## Benchmarking
35
+
36
+ - Uses benchmark-ips with `warmup: 1, time: 3`
37
+ - Run benchmarks sequentially to reduce variance
38
+ - For parameter sweeps: test multiple values in a single script with 3 runs each, report median
39
+ - Sister project **rbnng** (`/home/roadster/dev/oss/rbnng`) has identical bench structure for comparison
data/Gemfile CHANGED
@@ -1,10 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- # useful when working on czmq-ffi-gen in parallel
5
- # gem "czmq-ffi-gen", path: "../czmq-ffi-gen"
6
-
7
4
  group :development do
8
- gem 'codecov', require: false
9
5
  gem 'simplecov', require: false
10
6
  end
data/README.md CHANGED
@@ -1,224 +1,135 @@
1
- ![Specs status](https://github.com/paddor/cztop/workflows/STABLE%20API/badge.svg)
2
- ![Specs status](https://github.com/paddor/cztop/workflows/DRAFT%20API%20on%20Ruby%203.3/badge.svg)
3
- ![Specs status](https://github.com/paddor/cztop/workflows/DRAFT%20API%20on%20Ruby%203.4/badge.svg)
4
- [![codecov](https://codecov.io/gh/paddor/cztop/branch/master/graph/badge.svg?token=TnjOba97R7)](https://codecov.io/gh/paddor/cztop)
5
-
6
1
  # CZTop
7
2
 
8
- CZTop is a CZMQ binding for Ruby. It is based on
9
- [czmq-ffi-gen](https://github.com/paddor/czmq-ffi-gen), the generated low-level
10
- FFI binding of [CZMQ](https://github.com/zeromq/czmq) and has a focus on being
11
- easy to use for Rubyists (POLS) and providing first class support for security
12
- mechanisms (like CURVE).
3
+ [![CI](https://github.com/paddor/cztop/actions/workflows/ci.yml/badge.svg)](https://github.com/paddor/cztop/actions/workflows/ci.yml)
4
+ [![Gem Version](https://img.shields.io/gem/v/cztop?color=e9573f)](https://rubygems.org/gems/cztop)
5
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](LICENSE)
6
+ [![Ruby](https://img.shields.io/badge/Ruby-%3E%3D%203.3-CC342D?logo=ruby&logoColor=white)](https://www.ruby-lang.org)
13
7
 
8
+ Ruby FFI binding for [CZMQ](http://czmq.zeromq.org/) / [ZeroMQ](https://zeromq.org/) — high-performance asynchronous messaging for distributed systems.
14
9
 
15
- ## Example with Async
10
+ > **353k msg/s** inproc throughput | **49 µs** fiber roundtrip latency | nonblock fast path
16
11
 
17
- See [this example](https://github.com/paddor/cztop/blob/master/examples/async.rb):
12
+ ---
18
13
 
19
- ```ruby
20
- #! /usr/bin/env ruby
14
+ ## Highlights
21
15
 
22
- require 'bundler/inline'
16
+ - **All socket types** — req/rep, pub/sub, push/pull, dealer/router, xpub/xsub, pair, stream
17
+ - **Async-first** — first-class [async](https://github.com/socketry/async) fiber support, also works with plain threads
18
+ - **Ruby-idiomatic API** — messages as `Array<String>`, errors as exceptions, timeouts as `IO::TimeoutError`
23
19
 
24
- gemfile do
25
- source 'https://rubygems.org'
26
- gem 'cztop', path: '../../'
27
- gem 'async'
28
- end
20
+ ## Install
29
21
 
30
- ENDPOINT = 'inproc://req_rep_example'
31
- # ENDPOINT = 'ipc:///tmp/req_rep_example0'
32
- # ENDPOINT = 'tcp://localhost:5556'
22
+ Install CZMQ on your system:
33
23
 
34
- Async do |task|
35
- rep_task = task.async do |t|
36
- socket = CZTop::Socket::REP.new ENDPOINT
37
-
38
- loop do
39
- msg = socket.receive
40
- puts "<<< #{msg.to_a.inspect}"
41
- socket << msg.to_a.map(&:upcase)
42
- end
43
- ensure
44
- puts "REP done."
45
- end
24
+ ```sh
25
+ # Debian/Ubuntu
26
+ sudo apt install libczmq-dev
46
27
 
47
- task.async do
48
- socket = CZTop::Socket::REQ.new ENDPOINT
49
-
50
- 10.times do |i|
51
- socket << "foobar ##{i}"
52
- msg = socket.receive
53
- puts ">>> #{msg.to_a.inspect}"
54
- end
55
-
56
- puts "REQ done."
57
- rep_task.stop
58
- end
59
- end
28
+ # macOS
29
+ brew install czmq
60
30
  ```
61
31
 
32
+ Then add the gem:
62
33
 
63
- Output:
64
- ```
65
- $ cd examples
66
- $ time ./async.rb
67
- <<< ["foobar #0"]
68
- >>> ["FOOBAR #0"]
69
- <<< ["foobar #1"]
70
- >>> ["FOOBAR #1"]
71
- <<< ["foobar #2"]
72
- >>> ["FOOBAR #2"]
73
- <<< ["foobar #3"]
74
- >>> ["FOOBAR #3"]
75
- <<< ["foobar #4"]
76
- >>> ["FOOBAR #4"]
77
- <<< ["foobar #5"]
78
- >>> ["FOOBAR #5"]
79
- <<< ["foobar #6"]
80
- >>> ["FOOBAR #6"]
81
- <<< ["foobar #7"]
82
- >>> ["FOOBAR #7"]
83
- <<< ["foobar #8"]
84
- >>> ["FOOBAR #8"]
85
- <<< ["foobar #9"]
86
- >>> ["FOOBAR #9"]
87
- REQ done.
88
- REP done.
89
-
90
- ________________________________________________________
91
- Executed in 401.51 millis fish external
92
- usr time 308.44 millis 605.00 micros 307.83 millis
93
- sys time 40.08 millis 278.00 micros 39.81 millis
94
-
34
+ ```sh
35
+ gem install cztop
36
+ # or in Gemfile
37
+ gem 'cztop'
95
38
  ```
96
39
 
97
- A slightly more complex version (more sockets) is [here](https://github.com/paddor/cztop/blob/master/examples/massive_async.rb).
40
+ ## Quick Start
98
41
 
99
- ## Overview
42
+ ### Request / Reply
100
43
 
101
- ### Features
102
-
103
- * Ruby idiomatic API
104
- * compatible with Fiber Scheduler (only on Ruby >= 3.2)
105
- * errors as exceptions
106
- * CURVE security
107
- * supports CZMQ DRAFT API
108
- * extensive spec coverage
44
+ ```ruby
45
+ require 'cztop'
46
+ require 'async'
109
47
 
110
- ## Requirements
48
+ Async do |task|
49
+ rep = CZTop::Socket::REP.new('inproc://example')
50
+ req = CZTop::Socket::REQ.new('inproc://example')
111
51
 
52
+ task.async do
53
+ msg = rep.receive
54
+ rep << msg.map(&:upcase)
55
+ end
112
56
 
113
- * CZMQ >= 4.2
114
- * ZMQ >= 4.3
57
+ req << 'hello'
58
+ puts req.receive.inspect # => ["HELLO"]
59
+ end
60
+ ```
115
61
 
62
+ ### Pub / Sub
116
63
 
117
- On Ubuntu 20.04+:
64
+ ```ruby
65
+ Async do |task|
66
+ pub = CZTop::Socket::PUB.new('inproc://pubsub')
67
+ sub = CZTop::Socket::SUB.new('inproc://pubsub')
68
+ sub.subscribe('') # subscribe to all
118
69
 
119
- $ sudo apt install libczmq-dev
70
+ sleep 0.01 # allow connection to establish
120
71
 
121
- On macOS using Homebrew, run:
72
+ task.async { pub << 'news flash' }
73
+ puts sub.receive.inspect # => ["news flash"]
74
+ end
75
+ ```
122
76
 
123
- $ brew install czmq
77
+ ### Push / Pull (Pipeline)
124
78
 
125
- ### Supported Rubies
79
+ ```ruby
80
+ Async do
81
+ push = CZTop::Socket::PUSH.new('inproc://pipeline')
82
+ pull = CZTop::Socket::PULL.new('inproc://pipeline')
126
83
 
127
- At least:
84
+ push << 'work item'
85
+ puts pull.receive.inspect # => ["work item"]
86
+ end
87
+ ```
128
88
 
129
- * Ruby 3.0, 3.1, 3.2, 3.3
89
+ ## Socket Types
130
90
 
131
- ## Installation
91
+ | Pattern | Classes | Direction |
92
+ |---------|---------|-----------|
93
+ | Request/Reply | `REQ`, `REP` | bidirectional |
94
+ | Publish/Subscribe | `PUB`, `SUB`, `XPUB`, `XSUB` | unidirectional |
95
+ | Pipeline | `PUSH`, `PULL` | unidirectional |
96
+ | Routing | `DEALER`, `ROUTER` | bidirectional |
97
+ | Exclusive pair | `PAIR` | bidirectional |
98
+ | Raw TCP | `STREAM` | bidirectional |
132
99
 
133
- To use this gem, add this line to your application's Gemfile:
100
+ All classes live under `CZTop::Socket::`.
134
101
 
135
- ```ruby
136
- gem 'cztop'
137
- ```
102
+ ## Performance
138
103
 
139
- And then execute:
140
-
141
- $ bundle
142
-
143
- Or install it yourself as:
144
-
145
- $ gem install cztop
146
-
147
- ### Class Hierarchy
148
-
149
- Here's an overview of the core classes:
150
-
151
- * [CZTop](http://www.rubydoc.info/gems/cztop/CZTop)
152
- * [Actor](http://www.rubydoc.info/gems/cztop/CZTop)
153
- * [Authenticator](http://www.rubydoc.info/gems/cztop/CZTop/Authenticator)
154
- * [Beacon](http://www.rubydoc.info/gems/cztop/CZTop/Beacon)
155
- * [Certificate](http://www.rubydoc.info/gems/cztop/CZTop/Certificate)
156
- * [CertStore](http://www.rubydoc.info/gems/cztop/CZTop/CertStore)
157
- * [Config](http://www.rubydoc.info/gems/cztop/CZTop/Config)
158
- * [Frame](http://www.rubydoc.info/gems/cztop/CZTop/Frame)
159
- * [Message](http://www.rubydoc.info/gems/cztop/CZTop/Message)
160
- * [Monitor](http://www.rubydoc.info/gems/cztop/CZTop/Monitor)
161
- * [Metadata](http://www.rubydoc.info/gems/cztop/CZTop/Metadata)
162
- * [Proxy](http://www.rubydoc.info/gems/cztop/CZTop/Proxy)
163
- * [Poller](http://www.rubydoc.info/gems/cztop/CZTop/Poller) (based on `zmq_poller_*()` functions)
164
- * [Aggregated](http://www.rubydoc.info/gems/cztop/CZTop/Poller/Aggregated)
165
- * [ZPoller](http://www.rubydoc.info/gems/cztop/CZTop/Poller/ZPoller)
166
- * [Socket](http://www.rubydoc.info/gems/cztop/CZTop/Socket)
167
- * [REQ](http://www.rubydoc.info/gems/cztop/CZTop/Socket/REQ) < Socket
168
- * [REP](http://www.rubydoc.info/gems/cztop/CZTop/Socket/REP) < Socket
169
- * [ROUTER](http://www.rubydoc.info/gems/cztop/CZTop/Socket/ROUTER) < Socket
170
- * [DEALER](http://www.rubydoc.info/gems/cztop/CZTop/Socket/DEALER) < Socket
171
- * [PUSH](http://www.rubydoc.info/gems/cztop/CZTop/Socket/PUSH) < Socket
172
- * [PULL](http://www.rubydoc.info/gems/cztop/CZTop/Socket/PULL) < Socket
173
- * [PUB](http://www.rubydoc.info/gems/cztop/CZTop/Socket/PUB) < Socket
174
- * [SUB](http://www.rubydoc.info/gems/cztop/CZTop/Socket/SUB) < Socket
175
- * [XPUB](http://www.rubydoc.info/gems/cztop/CZTop/Socket/XPUB) < Socket
176
- * [XSUB](http://www.rubydoc.info/gems/cztop/CZTop/Socket/XSUB) < Socket
177
- * [PAIR](http://www.rubydoc.info/gems/cztop/CZTop/Socket/PAIR) < Socket
178
- * [STREAM](http://www.rubydoc.info/gems/cztop/CZTop/Socket/STREAM) < Socket
179
- * [CLIENT](http://www.rubydoc.info/gems/cztop/CZTop/Socket/CLIENT) < Socket
180
- * [SERVER](http://www.rubydoc.info/gems/cztop/CZTop/Socket/SERVER) < Socket
181
- * [RADIO](http://www.rubydoc.info/gems/cztop/CZTop/Socket/RADIO) < Socket
182
- * [DISH](http://www.rubydoc.info/gems/cztop/CZTop/Socket/DISH) < Socket
183
- * [SCATTER](http://www.rubydoc.info/gems/cztop/CZTop/Socket/SCATTER) < Socket
184
- * [GATHER](http://www.rubydoc.info/gems/cztop/CZTop/Socket/GATHER) < Socket
185
- * [Z85](http://www.rubydoc.info/gems/cztop/CZTop/Z85)
186
- * [Padded](http://www.rubydoc.info/gems/cztop/CZTop/Z85/Padded) < Z85
187
- * [Pipe](http://www.rubydoc.info/gems/cztop/CZTop/Z85/Pipe)
188
- * [ZAP](http://www.rubydoc.info/gems/cztop/CZTop/ZAP)
189
-
190
- More information in the [API documentation](http://www.rubydoc.info/github/paddor/cztop).
191
-
192
- ## Documentation
193
-
194
- The API should be fairly straight-forward to anyone who is familiar with CZMQ
195
- and Ruby. The following API documentation is currently available:
196
-
197
- * [YARD API documentation](http://www.rubydoc.info/gems/cztop) (release)
198
-
199
- Feel free to start a [wiki](https://github.com/paddor/cztop/wiki) page.
104
+ Benchmarked with benchmark-ips on Linux x86_64 (CZMQ 4.2.1, ZMQ 4.3.5, Ruby 4.0.1 +YJIT):
200
105
 
201
- ## Performance
106
+ #### Throughput (push/pull)
202
107
 
203
- CZTop is just a convenience layer on top of the thin czmq-ffi-gen library.
108
+ | | inproc | ipc | tcp |
109
+ |---|--------|-----|-----|
110
+ | **Async** | 284k/s | 17k/s | 14k/s |
111
+ | **Threads** | 353k/s | 25k/s | 21k/s |
204
112
 
205
- Make sure to check out the
206
- [perf](https://github.com/paddor/cztop/blob/master/perf) directory for latency
207
- and throughput measurement scripts.
113
+ #### Latency (req/rep roundtrip)
208
114
 
209
- ## Usage
115
+ | | inproc | ipc | tcp |
116
+ |---|--------|-----|-----|
117
+ | **Async** | 49 µs | 100 µs | 107 µs |
118
+ | **Threads** | 113 µs | 154 µs | 168 µs |
210
119
 
211
- See the [examples](https://github.com/paddor/cztop/blob/master/examples) directory for some examples.
120
+ Async fibers deliver 2.3x lower inproc latency thanks to cheap context switching. See [`bench/`](bench/) for full results and scripts.
212
121
 
122
+ ## API Reference
213
123
 
214
- ## Contributing
124
+ Full [API documentation](http://www.rubydoc.info/gems/cztop).
215
125
 
216
- Bug reports and pull requests are welcome on GitHub at https://github.com/paddor/cztop.
126
+ ## Development
217
127
 
218
- To run the tests before/after you made any changes to the source and have
219
- created a test case for it, use `rake spec`.
128
+ ```sh
129
+ bundle install
130
+ bundle exec rake
131
+ ```
220
132
 
221
133
  ## License
222
134
 
223
- The gem is available as open source under the terms of the [ISC License](http://opensource.org/licenses/ISC).
224
- See the [LICENSE](https://github.com/paddor/cztop/blob/master/LICENSE) file.
135
+ [ISC](LICENSE)