concurrent-c-node 0.14.0__tar.gz → 0.15.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: concurrent-c-node
3
- Version: 0.14.0
3
+ Version: 0.15.0
4
4
  Summary: JavaScript and npm packages from Python over the Concurrent-C bridge: one spawned Node child per domain, host-controlled lifetime.
5
5
  License: MIT
6
6
  Project-URL: Repository, https://github.com/sreekotay/concurrent-c
@@ -62,6 +62,7 @@ event-loop or GIL between them.
62
62
  pip install concurrent-c-node # needs node on PATH (or point at one)
63
63
  python -m cc_node.examples.use_node
64
64
  python -m cc_node.examples.bench_wire
65
+ python -m cc_node.benchmarks.multi_domain # N children, thread-fanned
65
66
  ```
66
67
 
67
68
  ## Measured (separate-process wire)
@@ -186,7 +187,9 @@ JS Promise you must await.
186
187
  **Wire cost vs tiny work.** Round trip is ~100µs class; a one-line JS
187
188
  helper on three numbers loses to pure Python. Prefer Python (or a native
188
189
  CC module) for small/hot work; use the bridge when Node/npm owns the
189
- kernel (crypto, parsers, large buffers via shm).
190
+ kernel (crypto, parsers, large buffers via shm). Multi-core: fan across
191
+ `create()` handles from threads —
192
+ `python -m cc_node.benchmarks.multi_domain` (~2.8× on 3 domains here).
190
193
 
191
194
  **Crash isolation, not a sandbox.** The child inherits your environment
192
195
  and privileges — do not evaluate untrusted JavaScript. `destroy()` is
@@ -214,16 +217,37 @@ speaks, from CC.
214
217
 
215
218
  ## Publishing
216
219
 
217
- From the Concurrent-C repo root (packs this wheel and the npm sibling):
220
+ **Preferred — PyPI Trusted Publishing (OIDC) from CI** (no API token):
221
+
222
+ 1. One-time on
223
+ [Publishing settings](https://pypi.org/manage/project/concurrent-c-node/settings/publishing/):
224
+ - Owner `sreekotay`, repository `concurrent-c`
225
+ - Workflow name `publish-cc-node.yml`
226
+ - Environment name `pypi`
227
+ 2. Create a GitHub Environment named `pypi` (optional reviewers encouraged).
228
+ 3. Bump `version` in `pyproject.toml`, commit + push, then:
229
+
230
+ ```
231
+ gh workflow run publish-cc-node.yml
232
+ # or: git tag cc-node-vX.Y.Z && git push --tags
233
+ ```
234
+
235
+ Local pack / npm sibling (PyPI defaults to CI OIDC after npm):
218
236
 
219
237
  ```
220
- ./scripts/publish_bridges.sh # → out/pypi/concurrent_c_node-* (+ npm tgz)
221
- ./scripts/publish_bridges.sh --publish # bump patch, pack, twine + npm publish
238
+ ./scripts/publish_bridges.sh --publish --minor
239
+ # npm is live; then commit+push bumps and:
240
+ gh workflow run publish-cc-node.yml
241
+
242
+ # local twine fallback:
243
+ ./scripts/publish_bridges.sh --publish --minor --pypi-twine
222
244
  ```
223
245
 
224
246
  A worked tour (builtin Node modules, chains, callbacks, thenables,
225
247
  buffers — no npm install needed):
226
- `python -m cc_node.examples.use_node`.
248
+ `python -m cc_node.examples.use_node`. Wire RTT / shm:
249
+ `python -m cc_node.examples.bench_wire`. Multi-core domains (threads):
250
+ `python -m cc_node.benchmarks.multi_domain`.
227
251
 
228
252
  Adversarial multi-child storm (escaped closures, cooperative
229
253
  fanout-destroy, abort inject, handle-leak / RSS soaks):
@@ -51,6 +51,7 @@ event-loop or GIL between them.
51
51
  pip install concurrent-c-node # needs node on PATH (or point at one)
52
52
  python -m cc_node.examples.use_node
53
53
  python -m cc_node.examples.bench_wire
54
+ python -m cc_node.benchmarks.multi_domain # N children, thread-fanned
54
55
  ```
55
56
 
56
57
  ## Measured (separate-process wire)
@@ -175,7 +176,9 @@ JS Promise you must await.
175
176
  **Wire cost vs tiny work.** Round trip is ~100µs class; a one-line JS
176
177
  helper on three numbers loses to pure Python. Prefer Python (or a native
177
178
  CC module) for small/hot work; use the bridge when Node/npm owns the
178
- kernel (crypto, parsers, large buffers via shm).
179
+ kernel (crypto, parsers, large buffers via shm). Multi-core: fan across
180
+ `create()` handles from threads —
181
+ `python -m cc_node.benchmarks.multi_domain` (~2.8× on 3 domains here).
179
182
 
180
183
  **Crash isolation, not a sandbox.** The child inherits your environment
181
184
  and privileges — do not evaluate untrusted JavaScript. `destroy()` is
@@ -203,16 +206,37 @@ speaks, from CC.
203
206
 
204
207
  ## Publishing
205
208
 
206
- From the Concurrent-C repo root (packs this wheel and the npm sibling):
209
+ **Preferred — PyPI Trusted Publishing (OIDC) from CI** (no API token):
210
+
211
+ 1. One-time on
212
+ [Publishing settings](https://pypi.org/manage/project/concurrent-c-node/settings/publishing/):
213
+ - Owner `sreekotay`, repository `concurrent-c`
214
+ - Workflow name `publish-cc-node.yml`
215
+ - Environment name `pypi`
216
+ 2. Create a GitHub Environment named `pypi` (optional reviewers encouraged).
217
+ 3. Bump `version` in `pyproject.toml`, commit + push, then:
218
+
219
+ ```
220
+ gh workflow run publish-cc-node.yml
221
+ # or: git tag cc-node-vX.Y.Z && git push --tags
222
+ ```
223
+
224
+ Local pack / npm sibling (PyPI defaults to CI OIDC after npm):
207
225
 
208
226
  ```
209
- ./scripts/publish_bridges.sh # → out/pypi/concurrent_c_node-* (+ npm tgz)
210
- ./scripts/publish_bridges.sh --publish # bump patch, pack, twine + npm publish
227
+ ./scripts/publish_bridges.sh --publish --minor
228
+ # npm is live; then commit+push bumps and:
229
+ gh workflow run publish-cc-node.yml
230
+
231
+ # local twine fallback:
232
+ ./scripts/publish_bridges.sh --publish --minor --pypi-twine
211
233
  ```
212
234
 
213
235
  A worked tour (builtin Node modules, chains, callbacks, thenables,
214
236
  buffers — no npm install needed):
215
- `python -m cc_node.examples.use_node`.
237
+ `python -m cc_node.examples.use_node`. Wire RTT / shm:
238
+ `python -m cc_node.examples.bench_wire`. Multi-core domains (threads):
239
+ `python -m cc_node.benchmarks.multi_domain`.
216
240
 
217
241
  Adversarial multi-child storm (escaped closures, cooperative
218
242
  fanout-destroy, abort inject, handle-leak / RSS soaks):
@@ -30,7 +30,7 @@ import subprocess
30
30
  import tempfile
31
31
 
32
32
  __all__ = ["create", "JsError", "JsHandle", "__version__"]
33
- __version__ = "0.12.1"
33
+ __version__ = "0.13.0"
34
34
 
35
35
  # Typed buffers cross as typed arrays; big ones spill through shared
36
36
  # memory (tmpfs where available) — one memcpy per side, receiver
@@ -0,0 +1 @@
1
+ # Measurement scripts for concurrent-c-node (RESULT lines, machine-comparable).
@@ -0,0 +1,60 @@
1
+ """N node children on N cores — measured with real overlap.
2
+
3
+ python -m cc_node.benchmarks.multi_domain
4
+
5
+ Wire RTT / shm live in ``cc_node.examples.bench_wire``. This file only
6
+ answers the multi-domain question: sequential calls on one child vs the
7
+ same work fanned across threads into separate children.
8
+ """
9
+ import time
10
+ from concurrent.futures import ThreadPoolExecutor
11
+
12
+ import cc_node
13
+
14
+ WORK = """
15
+ (iterations) => {
16
+ let s = 0;
17
+ for (let i = 0; i < iterations; i++)
18
+ s += Math.sqrt(i) * Math.sin(i / 1000);
19
+ return s;
20
+ }
21
+ """
22
+
23
+
24
+ def main():
25
+ n_dom = 3
26
+ iters = 40_000_000
27
+
28
+ with cc_node.create() as js:
29
+ f = js.eval(WORK)
30
+ f(iters // 20)
31
+ t0 = time.perf_counter()
32
+ for _ in range(n_dom):
33
+ f(iters)
34
+ seq = time.perf_counter() - t0
35
+ print("RESULT seq_s %.3f" % seq)
36
+
37
+ domains = [cc_node.create() for _ in range(n_dom)]
38
+ try:
39
+ fns = [d.eval(WORK) for d in domains]
40
+ for f in fns:
41
+ f(iters // 20)
42
+
43
+ def run(f):
44
+ return f(iters)
45
+
46
+ t0 = time.perf_counter()
47
+ with ThreadPoolExecutor(max_workers=n_dom) as pool:
48
+ list(pool.map(run, fns))
49
+ par = time.perf_counter() - t0
50
+ finally:
51
+ for d in domains:
52
+ d.destroy()
53
+
54
+ print("RESULT par_s %.3f" % par)
55
+ print("RESULT speedup %.2f" % (seq / par if par else 0))
56
+ print("done")
57
+
58
+
59
+ if __name__ == "__main__":
60
+ main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: concurrent-c-node
3
- Version: 0.14.0
3
+ Version: 0.15.0
4
4
  Summary: JavaScript and npm packages from Python over the Concurrent-C bridge: one spawned Node child per domain, host-controlled lifetime.
5
5
  License: MIT
6
6
  Project-URL: Repository, https://github.com/sreekotay/concurrent-c
@@ -62,6 +62,7 @@ event-loop or GIL between them.
62
62
  pip install concurrent-c-node # needs node on PATH (or point at one)
63
63
  python -m cc_node.examples.use_node
64
64
  python -m cc_node.examples.bench_wire
65
+ python -m cc_node.benchmarks.multi_domain # N children, thread-fanned
65
66
  ```
66
67
 
67
68
  ## Measured (separate-process wire)
@@ -186,7 +187,9 @@ JS Promise you must await.
186
187
  **Wire cost vs tiny work.** Round trip is ~100µs class; a one-line JS
187
188
  helper on three numbers loses to pure Python. Prefer Python (or a native
188
189
  CC module) for small/hot work; use the bridge when Node/npm owns the
189
- kernel (crypto, parsers, large buffers via shm).
190
+ kernel (crypto, parsers, large buffers via shm). Multi-core: fan across
191
+ `create()` handles from threads —
192
+ `python -m cc_node.benchmarks.multi_domain` (~2.8× on 3 domains here).
190
193
 
191
194
  **Crash isolation, not a sandbox.** The child inherits your environment
192
195
  and privileges — do not evaluate untrusted JavaScript. `destroy()` is
@@ -214,16 +217,37 @@ speaks, from CC.
214
217
 
215
218
  ## Publishing
216
219
 
217
- From the Concurrent-C repo root (packs this wheel and the npm sibling):
220
+ **Preferred — PyPI Trusted Publishing (OIDC) from CI** (no API token):
221
+
222
+ 1. One-time on
223
+ [Publishing settings](https://pypi.org/manage/project/concurrent-c-node/settings/publishing/):
224
+ - Owner `sreekotay`, repository `concurrent-c`
225
+ - Workflow name `publish-cc-node.yml`
226
+ - Environment name `pypi`
227
+ 2. Create a GitHub Environment named `pypi` (optional reviewers encouraged).
228
+ 3. Bump `version` in `pyproject.toml`, commit + push, then:
229
+
230
+ ```
231
+ gh workflow run publish-cc-node.yml
232
+ # or: git tag cc-node-vX.Y.Z && git push --tags
233
+ ```
234
+
235
+ Local pack / npm sibling (PyPI defaults to CI OIDC after npm):
218
236
 
219
237
  ```
220
- ./scripts/publish_bridges.sh # → out/pypi/concurrent_c_node-* (+ npm tgz)
221
- ./scripts/publish_bridges.sh --publish # bump patch, pack, twine + npm publish
238
+ ./scripts/publish_bridges.sh --publish --minor
239
+ # npm is live; then commit+push bumps and:
240
+ gh workflow run publish-cc-node.yml
241
+
242
+ # local twine fallback:
243
+ ./scripts/publish_bridges.sh --publish --minor --pypi-twine
222
244
  ```
223
245
 
224
246
  A worked tour (builtin Node modules, chains, callbacks, thenables,
225
247
  buffers — no npm install needed):
226
- `python -m cc_node.examples.use_node`.
248
+ `python -m cc_node.examples.use_node`. Wire RTT / shm:
249
+ `python -m cc_node.examples.bench_wire`. Multi-core domains (threads):
250
+ `python -m cc_node.benchmarks.multi_domain`.
227
251
 
228
252
  Adversarial multi-child storm (escaped closures, cooperative
229
253
  fanout-destroy, abort inject, handle-leak / RSS soaks):
@@ -2,6 +2,8 @@ README.md
2
2
  pyproject.toml
3
3
  cc_node/__init__.py
4
4
  cc_node/broker.cjs
5
+ cc_node/benchmarks/__init__.py
6
+ cc_node/benchmarks/multi_domain.py
5
7
  cc_node/examples/__init__.py
6
8
  cc_node/examples/bench_wire.py
7
9
  cc_node/examples/use_node.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "concurrent-c-node"
7
- version = "0.14.0"
7
+ version = "0.15.0"
8
8
  description = "JavaScript and npm packages from Python over the Concurrent-C bridge: one spawned Node child per domain, host-controlled lifetime."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -16,8 +16,9 @@ Repository = "https://github.com/sreekotay/concurrent-c"
16
16
  Documentation = "https://github.com/sreekotay/concurrent-c/blob/main/pypi/cc-node/README.md"
17
17
 
18
18
  [tool.setuptools]
19
- packages = ["cc_node", "cc_node.examples"]
19
+ packages = ["cc_node", "cc_node.examples", "cc_node.benchmarks"]
20
20
 
21
21
  [tool.setuptools.package-data]
22
22
  cc_node = ["broker.cjs"]
23
23
  "cc_node.examples" = ["*.py"]
24
+ "cc_node.benchmarks" = ["*.py"]