concurrent-c-node 0.10.0__tar.gz → 0.12.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.
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/PKG-INFO +62 -44
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/README.md +61 -43
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/concurrent_c_node.egg-info/PKG-INFO +62 -44
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/pyproject.toml +1 -1
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/cc_node/__init__.py +0 -0
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/cc_node/broker.cjs +0 -0
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/cc_node/examples/__init__.py +0 -0
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/cc_node/examples/bench_wire.py +0 -0
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/cc_node/examples/use_node.py +0 -0
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/concurrent_c_node.egg-info/SOURCES.txt +0 -0
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/concurrent_c_node.egg-info/dependency_links.txt +0 -0
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/concurrent_c_node.egg-info/top_level.txt +0 -0
- {concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: concurrent-c-node
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.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
|
|
@@ -24,7 +24,7 @@ package bridge):
|
|
|
24
24
|
```python
|
|
25
25
|
import cc_node
|
|
26
26
|
|
|
27
|
-
js = cc_node.create() #
|
|
27
|
+
js = cc_node.create() # always a SEPARATE node process
|
|
28
28
|
_ = js.require('lodash') # resolved from YOUR cwd's node_modules
|
|
29
29
|
_.chunk([1, 2, 3, 4, 5], 2) # [[1, 2], [3, 4], [5]]
|
|
30
30
|
_.sortBy([{'n': 3}, {'n': 1}], 'n') # dicts cross as objects, and back
|
|
@@ -35,12 +35,28 @@ semver.satisfies('1.2.3', '^1.0.0') # True
|
|
|
35
35
|
js.destroy() # or: with cc_node.create() as js: ...
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
## Separate process by design
|
|
39
|
+
|
|
40
|
+
Unlike [`concurrent-c-python`](https://github.com/sreekotay/concurrent-c/tree/main/npm/cc-python)
|
|
41
|
+
(whose **default** embeds libpython in the Node process, with
|
|
42
|
+
`{ isolated: true }` as the child-process opt-in), **every**
|
|
43
|
+
`cc_node.create()` is already the isolated tier: one spawned `node`
|
|
44
|
+
child per domain. There is no in-process Node embed from Python —
|
|
45
|
+
you get real Node (full stdlib, native addons, whatever `npm install`
|
|
46
|
+
put next to your program), crash isolation, and a wire you can measure.
|
|
47
|
+
|
|
48
|
+
N domains are N OS processes: **full multi-core speedup** — fan work
|
|
49
|
+
across `create()` handles and they run on separate cores, no shared
|
|
50
|
+
event-loop or GIL between them.
|
|
51
|
+
|
|
52
|
+
| | this package — separate `node` process | Concurrent-C hosted (not this wheel) |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| API | `cc_node.create()` from Python | `cc_js_new(false, &a)` in a `.ccs` program |
|
|
55
|
+
| Where JS runs | own `node` child | libnode in the CC process |
|
|
56
|
+
| Hot call | **~105µs** wire RTT | sub-µs (needs `libnode-dev`) |
|
|
57
|
+
| Bulk buffers | shm spill — 8MB in **9.5ms** (52× a JSON list) | in-process |
|
|
58
|
+
| Parallelism | **N children = N cores — full multi-core speedup** | one process (V8's rule) |
|
|
59
|
+
| Crash | child dies → error; Python parent lives | shared fate with the host |
|
|
44
60
|
|
|
45
61
|
```
|
|
46
62
|
pip install concurrent-c-node # needs node on PATH (or point at one)
|
|
@@ -48,9 +64,39 @@ python -m cc_node.examples.use_node
|
|
|
48
64
|
python -m cc_node.examples.bench_wire
|
|
49
65
|
```
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
## Measured (separate-process wire)
|
|
68
|
+
|
|
69
|
+
From `python -m cc_node.examples.bench_wire` (sources under
|
|
70
|
+
[`cc_node/examples/`](https://github.com/sreekotay/concurrent-c/blob/main/pypi/cc-node/cc_node/examples/))
|
|
71
|
+
on a 4-vCPU x86-64 box, node 22 / python 3.11
|
|
72
|
+
([`perf/baselines/cc_node_bridge_py_20260810.txt`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/cc_node_bridge_py_20260810.txt);
|
|
73
|
+
catalog: [`perf/baselines/README.md`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/README.md)):
|
|
74
|
+
|
|
75
|
+
| what | result |
|
|
76
|
+
|---|---|
|
|
77
|
+
| spawn a domain (node child, first eval) | **28ms** |
|
|
78
|
+
| wire round trip (smallest call) | **105µs** |
|
|
79
|
+
| Python-callback round trip (JS → Python → JS) | **153µs** |
|
|
80
|
+
| 8MB `array('d')` argument, shm spill | **9.5ms** |
|
|
81
|
+
| the same 8MB as a JSON list | 499ms — the spill is **52x** |
|
|
82
|
+
|
|
83
|
+
The wire is strict request/response JSON on dedicated fds — replies
|
|
84
|
+
pair by request id, and stdio stays yours, so `console.log` in
|
|
85
|
+
evaluated JS reaches the real stdout and can never collide with a
|
|
86
|
+
protocol reply — with the shared-memory spill for bulk data (private
|
|
87
|
+
0700 per-bridge directory, 0600 exclusive-create files, removed with
|
|
88
|
+
the bridge). The same discipline concurrent-c-python's
|
|
89
|
+
`{ isolated: true }` domains speak, mirrored.
|
|
90
|
+
|
|
91
|
+
One boundary, stated plainly: the domain is **crash isolation, not a
|
|
92
|
+
security sandbox** — the node child inherits your environment and runs
|
|
93
|
+
with your OS privileges, so do not run untrusted JavaScript through
|
|
94
|
+
it.
|
|
95
|
+
|
|
96
|
+
The bridge is **pure Python, stdlib only** — no compiled code, no
|
|
97
|
+
dependencies, nothing to build. Import stays `import cc_node`.
|
|
98
|
+
Examples ship in the wheel. Same domain model and materialization
|
|
99
|
+
rules as the npm sibling, pointed the other way:
|
|
54
100
|
|
|
55
101
|
- **Values**: plain data (finite numbers, strings, booleans, `None`,
|
|
56
102
|
lists/dicts of the same) crosses by value; everything else is a live
|
|
@@ -129,9 +175,11 @@ And *which packages* it sees is the working directory's
|
|
|
129
175
|
Run Python in your project, get your project's packages: `npm install`
|
|
130
176
|
next to your program is the whole setup.
|
|
131
177
|
|
|
132
|
-
|
|
133
|
-
tier
|
|
134
|
-
[`examples/js/jsdemo.shcc`](https://github.com/sreekotay/concurrent-c/blob/main/examples/js/jsdemo.shcc)
|
|
178
|
+
Writing Concurrent-C itself rather than Python? The zero-IPC hosted
|
|
179
|
+
tier is `cc_js_new(false, &a)` (needs libnode) —
|
|
180
|
+
[`examples/js/jsdemo.shcc`](https://github.com/sreekotay/concurrent-c/blob/main/examples/js/jsdemo.shcc);
|
|
181
|
+
`cc_js_new(true, &a)` is the same separate-process wire this package
|
|
182
|
+
speaks, from CC.
|
|
135
183
|
|
|
136
184
|
## Publishing
|
|
137
185
|
|
|
@@ -142,36 +190,6 @@ From the Concurrent-C repo root (packs this wheel and the npm sibling):
|
|
|
142
190
|
./scripts/publish_bridges.sh --publish # bump patch, pack, twine + npm publish
|
|
143
191
|
```
|
|
144
192
|
|
|
145
|
-
## Measured
|
|
146
|
-
|
|
147
|
-
From `python -m cc_node.examples.bench_wire` (sources under
|
|
148
|
-
[`cc_node/examples/`](https://github.com/sreekotay/concurrent-c/blob/main/pypi/cc-node/cc_node/examples/))
|
|
149
|
-
on a 4-vCPU x86-64 box, node 22 / python 3.11
|
|
150
|
-
([`perf/baselines/cc_node_bridge_py_20260810.txt`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/cc_node_bridge_py_20260810.txt);
|
|
151
|
-
catalog: [`perf/baselines/README.md`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/README.md)):
|
|
152
|
-
|
|
153
|
-
| what | result |
|
|
154
|
-
|---|---|
|
|
155
|
-
| spawn a domain (node child, first eval) | 28ms |
|
|
156
|
-
| wire round trip (smallest call) | 105µs |
|
|
157
|
-
| Python-callback round trip (JS → Python → JS) | 153µs |
|
|
158
|
-
| 8MB `array('d')` argument, shm spill | **9.5ms** |
|
|
159
|
-
| the same 8MB as a JSON list | 499ms — the spill is **52x** |
|
|
160
|
-
|
|
161
|
-
The wire is strict request/response JSON on dedicated fds — replies
|
|
162
|
-
pair by request id, and stdio stays yours, so `console.log` in
|
|
163
|
-
evaluated JS reaches the real stdout and can never collide with a
|
|
164
|
-
protocol reply — with the shared-memory spill for bulk data (private
|
|
165
|
-
0700 per-bridge directory, 0600 exclusive-create files, removed with
|
|
166
|
-
the bridge). The same discipline concurrent-c-python's isolated
|
|
167
|
-
domains speak, mirrored. True pinned zero-copy leases remain future
|
|
168
|
-
work.
|
|
169
|
-
|
|
170
|
-
One boundary, stated plainly: the domain is **crash isolation, not a
|
|
171
|
-
security sandbox** — the node child inherits your environment and runs
|
|
172
|
-
with your OS privileges, so do not run untrusted JavaScript through
|
|
173
|
-
it.
|
|
174
|
-
|
|
175
193
|
A worked tour (builtin Node modules, chains, callbacks, thenables,
|
|
176
194
|
buffers — no npm install needed):
|
|
177
195
|
`python -m cc_node.examples.use_node`.
|
|
@@ -13,7 +13,7 @@ package bridge):
|
|
|
13
13
|
```python
|
|
14
14
|
import cc_node
|
|
15
15
|
|
|
16
|
-
js = cc_node.create() #
|
|
16
|
+
js = cc_node.create() # always a SEPARATE node process
|
|
17
17
|
_ = js.require('lodash') # resolved from YOUR cwd's node_modules
|
|
18
18
|
_.chunk([1, 2, 3, 4, 5], 2) # [[1, 2], [3, 4], [5]]
|
|
19
19
|
_.sortBy([{'n': 3}, {'n': 1}], 'n') # dicts cross as objects, and back
|
|
@@ -24,12 +24,28 @@ semver.satisfies('1.2.3', '^1.0.0') # True
|
|
|
24
24
|
js.destroy() # or: with cc_node.create() as js: ...
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
## Separate process by design
|
|
28
|
+
|
|
29
|
+
Unlike [`concurrent-c-python`](https://github.com/sreekotay/concurrent-c/tree/main/npm/cc-python)
|
|
30
|
+
(whose **default** embeds libpython in the Node process, with
|
|
31
|
+
`{ isolated: true }` as the child-process opt-in), **every**
|
|
32
|
+
`cc_node.create()` is already the isolated tier: one spawned `node`
|
|
33
|
+
child per domain. There is no in-process Node embed from Python —
|
|
34
|
+
you get real Node (full stdlib, native addons, whatever `npm install`
|
|
35
|
+
put next to your program), crash isolation, and a wire you can measure.
|
|
36
|
+
|
|
37
|
+
N domains are N OS processes: **full multi-core speedup** — fan work
|
|
38
|
+
across `create()` handles and they run on separate cores, no shared
|
|
39
|
+
event-loop or GIL between them.
|
|
40
|
+
|
|
41
|
+
| | this package — separate `node` process | Concurrent-C hosted (not this wheel) |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| API | `cc_node.create()` from Python | `cc_js_new(false, &a)` in a `.ccs` program |
|
|
44
|
+
| Where JS runs | own `node` child | libnode in the CC process |
|
|
45
|
+
| Hot call | **~105µs** wire RTT | sub-µs (needs `libnode-dev`) |
|
|
46
|
+
| Bulk buffers | shm spill — 8MB in **9.5ms** (52× a JSON list) | in-process |
|
|
47
|
+
| Parallelism | **N children = N cores — full multi-core speedup** | one process (V8's rule) |
|
|
48
|
+
| Crash | child dies → error; Python parent lives | shared fate with the host |
|
|
33
49
|
|
|
34
50
|
```
|
|
35
51
|
pip install concurrent-c-node # needs node on PATH (or point at one)
|
|
@@ -37,9 +53,39 @@ python -m cc_node.examples.use_node
|
|
|
37
53
|
python -m cc_node.examples.bench_wire
|
|
38
54
|
```
|
|
39
55
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
## Measured (separate-process wire)
|
|
57
|
+
|
|
58
|
+
From `python -m cc_node.examples.bench_wire` (sources under
|
|
59
|
+
[`cc_node/examples/`](https://github.com/sreekotay/concurrent-c/blob/main/pypi/cc-node/cc_node/examples/))
|
|
60
|
+
on a 4-vCPU x86-64 box, node 22 / python 3.11
|
|
61
|
+
([`perf/baselines/cc_node_bridge_py_20260810.txt`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/cc_node_bridge_py_20260810.txt);
|
|
62
|
+
catalog: [`perf/baselines/README.md`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/README.md)):
|
|
63
|
+
|
|
64
|
+
| what | result |
|
|
65
|
+
|---|---|
|
|
66
|
+
| spawn a domain (node child, first eval) | **28ms** |
|
|
67
|
+
| wire round trip (smallest call) | **105µs** |
|
|
68
|
+
| Python-callback round trip (JS → Python → JS) | **153µs** |
|
|
69
|
+
| 8MB `array('d')` argument, shm spill | **9.5ms** |
|
|
70
|
+
| the same 8MB as a JSON list | 499ms — the spill is **52x** |
|
|
71
|
+
|
|
72
|
+
The wire is strict request/response JSON on dedicated fds — replies
|
|
73
|
+
pair by request id, and stdio stays yours, so `console.log` in
|
|
74
|
+
evaluated JS reaches the real stdout and can never collide with a
|
|
75
|
+
protocol reply — with the shared-memory spill for bulk data (private
|
|
76
|
+
0700 per-bridge directory, 0600 exclusive-create files, removed with
|
|
77
|
+
the bridge). The same discipline concurrent-c-python's
|
|
78
|
+
`{ isolated: true }` domains speak, mirrored.
|
|
79
|
+
|
|
80
|
+
One boundary, stated plainly: the domain is **crash isolation, not a
|
|
81
|
+
security sandbox** — the node child inherits your environment and runs
|
|
82
|
+
with your OS privileges, so do not run untrusted JavaScript through
|
|
83
|
+
it.
|
|
84
|
+
|
|
85
|
+
The bridge is **pure Python, stdlib only** — no compiled code, no
|
|
86
|
+
dependencies, nothing to build. Import stays `import cc_node`.
|
|
87
|
+
Examples ship in the wheel. Same domain model and materialization
|
|
88
|
+
rules as the npm sibling, pointed the other way:
|
|
43
89
|
|
|
44
90
|
- **Values**: plain data (finite numbers, strings, booleans, `None`,
|
|
45
91
|
lists/dicts of the same) crosses by value; everything else is a live
|
|
@@ -118,9 +164,11 @@ And *which packages* it sees is the working directory's
|
|
|
118
164
|
Run Python in your project, get your project's packages: `npm install`
|
|
119
165
|
next to your program is the whole setup.
|
|
120
166
|
|
|
121
|
-
|
|
122
|
-
tier
|
|
123
|
-
[`examples/js/jsdemo.shcc`](https://github.com/sreekotay/concurrent-c/blob/main/examples/js/jsdemo.shcc)
|
|
167
|
+
Writing Concurrent-C itself rather than Python? The zero-IPC hosted
|
|
168
|
+
tier is `cc_js_new(false, &a)` (needs libnode) —
|
|
169
|
+
[`examples/js/jsdemo.shcc`](https://github.com/sreekotay/concurrent-c/blob/main/examples/js/jsdemo.shcc);
|
|
170
|
+
`cc_js_new(true, &a)` is the same separate-process wire this package
|
|
171
|
+
speaks, from CC.
|
|
124
172
|
|
|
125
173
|
## Publishing
|
|
126
174
|
|
|
@@ -131,36 +179,6 @@ From the Concurrent-C repo root (packs this wheel and the npm sibling):
|
|
|
131
179
|
./scripts/publish_bridges.sh --publish # bump patch, pack, twine + npm publish
|
|
132
180
|
```
|
|
133
181
|
|
|
134
|
-
## Measured
|
|
135
|
-
|
|
136
|
-
From `python -m cc_node.examples.bench_wire` (sources under
|
|
137
|
-
[`cc_node/examples/`](https://github.com/sreekotay/concurrent-c/blob/main/pypi/cc-node/cc_node/examples/))
|
|
138
|
-
on a 4-vCPU x86-64 box, node 22 / python 3.11
|
|
139
|
-
([`perf/baselines/cc_node_bridge_py_20260810.txt`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/cc_node_bridge_py_20260810.txt);
|
|
140
|
-
catalog: [`perf/baselines/README.md`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/README.md)):
|
|
141
|
-
|
|
142
|
-
| what | result |
|
|
143
|
-
|---|---|
|
|
144
|
-
| spawn a domain (node child, first eval) | 28ms |
|
|
145
|
-
| wire round trip (smallest call) | 105µs |
|
|
146
|
-
| Python-callback round trip (JS → Python → JS) | 153µs |
|
|
147
|
-
| 8MB `array('d')` argument, shm spill | **9.5ms** |
|
|
148
|
-
| the same 8MB as a JSON list | 499ms — the spill is **52x** |
|
|
149
|
-
|
|
150
|
-
The wire is strict request/response JSON on dedicated fds — replies
|
|
151
|
-
pair by request id, and stdio stays yours, so `console.log` in
|
|
152
|
-
evaluated JS reaches the real stdout and can never collide with a
|
|
153
|
-
protocol reply — with the shared-memory spill for bulk data (private
|
|
154
|
-
0700 per-bridge directory, 0600 exclusive-create files, removed with
|
|
155
|
-
the bridge). The same discipline concurrent-c-python's isolated
|
|
156
|
-
domains speak, mirrored. True pinned zero-copy leases remain future
|
|
157
|
-
work.
|
|
158
|
-
|
|
159
|
-
One boundary, stated plainly: the domain is **crash isolation, not a
|
|
160
|
-
security sandbox** — the node child inherits your environment and runs
|
|
161
|
-
with your OS privileges, so do not run untrusted JavaScript through
|
|
162
|
-
it.
|
|
163
|
-
|
|
164
182
|
A worked tour (builtin Node modules, chains, callbacks, thenables,
|
|
165
183
|
buffers — no npm install needed):
|
|
166
184
|
`python -m cc_node.examples.use_node`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: concurrent-c-node
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.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
|
|
@@ -24,7 +24,7 @@ package bridge):
|
|
|
24
24
|
```python
|
|
25
25
|
import cc_node
|
|
26
26
|
|
|
27
|
-
js = cc_node.create() #
|
|
27
|
+
js = cc_node.create() # always a SEPARATE node process
|
|
28
28
|
_ = js.require('lodash') # resolved from YOUR cwd's node_modules
|
|
29
29
|
_.chunk([1, 2, 3, 4, 5], 2) # [[1, 2], [3, 4], [5]]
|
|
30
30
|
_.sortBy([{'n': 3}, {'n': 1}], 'n') # dicts cross as objects, and back
|
|
@@ -35,12 +35,28 @@ semver.satisfies('1.2.3', '^1.0.0') # True
|
|
|
35
35
|
js.destroy() # or: with cc_node.create() as js: ...
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
## Separate process by design
|
|
39
|
+
|
|
40
|
+
Unlike [`concurrent-c-python`](https://github.com/sreekotay/concurrent-c/tree/main/npm/cc-python)
|
|
41
|
+
(whose **default** embeds libpython in the Node process, with
|
|
42
|
+
`{ isolated: true }` as the child-process opt-in), **every**
|
|
43
|
+
`cc_node.create()` is already the isolated tier: one spawned `node`
|
|
44
|
+
child per domain. There is no in-process Node embed from Python —
|
|
45
|
+
you get real Node (full stdlib, native addons, whatever `npm install`
|
|
46
|
+
put next to your program), crash isolation, and a wire you can measure.
|
|
47
|
+
|
|
48
|
+
N domains are N OS processes: **full multi-core speedup** — fan work
|
|
49
|
+
across `create()` handles and they run on separate cores, no shared
|
|
50
|
+
event-loop or GIL between them.
|
|
51
|
+
|
|
52
|
+
| | this package — separate `node` process | Concurrent-C hosted (not this wheel) |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| API | `cc_node.create()` from Python | `cc_js_new(false, &a)` in a `.ccs` program |
|
|
55
|
+
| Where JS runs | own `node` child | libnode in the CC process |
|
|
56
|
+
| Hot call | **~105µs** wire RTT | sub-µs (needs `libnode-dev`) |
|
|
57
|
+
| Bulk buffers | shm spill — 8MB in **9.5ms** (52× a JSON list) | in-process |
|
|
58
|
+
| Parallelism | **N children = N cores — full multi-core speedup** | one process (V8's rule) |
|
|
59
|
+
| Crash | child dies → error; Python parent lives | shared fate with the host |
|
|
44
60
|
|
|
45
61
|
```
|
|
46
62
|
pip install concurrent-c-node # needs node on PATH (or point at one)
|
|
@@ -48,9 +64,39 @@ python -m cc_node.examples.use_node
|
|
|
48
64
|
python -m cc_node.examples.bench_wire
|
|
49
65
|
```
|
|
50
66
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
## Measured (separate-process wire)
|
|
68
|
+
|
|
69
|
+
From `python -m cc_node.examples.bench_wire` (sources under
|
|
70
|
+
[`cc_node/examples/`](https://github.com/sreekotay/concurrent-c/blob/main/pypi/cc-node/cc_node/examples/))
|
|
71
|
+
on a 4-vCPU x86-64 box, node 22 / python 3.11
|
|
72
|
+
([`perf/baselines/cc_node_bridge_py_20260810.txt`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/cc_node_bridge_py_20260810.txt);
|
|
73
|
+
catalog: [`perf/baselines/README.md`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/README.md)):
|
|
74
|
+
|
|
75
|
+
| what | result |
|
|
76
|
+
|---|---|
|
|
77
|
+
| spawn a domain (node child, first eval) | **28ms** |
|
|
78
|
+
| wire round trip (smallest call) | **105µs** |
|
|
79
|
+
| Python-callback round trip (JS → Python → JS) | **153µs** |
|
|
80
|
+
| 8MB `array('d')` argument, shm spill | **9.5ms** |
|
|
81
|
+
| the same 8MB as a JSON list | 499ms — the spill is **52x** |
|
|
82
|
+
|
|
83
|
+
The wire is strict request/response JSON on dedicated fds — replies
|
|
84
|
+
pair by request id, and stdio stays yours, so `console.log` in
|
|
85
|
+
evaluated JS reaches the real stdout and can never collide with a
|
|
86
|
+
protocol reply — with the shared-memory spill for bulk data (private
|
|
87
|
+
0700 per-bridge directory, 0600 exclusive-create files, removed with
|
|
88
|
+
the bridge). The same discipline concurrent-c-python's
|
|
89
|
+
`{ isolated: true }` domains speak, mirrored.
|
|
90
|
+
|
|
91
|
+
One boundary, stated plainly: the domain is **crash isolation, not a
|
|
92
|
+
security sandbox** — the node child inherits your environment and runs
|
|
93
|
+
with your OS privileges, so do not run untrusted JavaScript through
|
|
94
|
+
it.
|
|
95
|
+
|
|
96
|
+
The bridge is **pure Python, stdlib only** — no compiled code, no
|
|
97
|
+
dependencies, nothing to build. Import stays `import cc_node`.
|
|
98
|
+
Examples ship in the wheel. Same domain model and materialization
|
|
99
|
+
rules as the npm sibling, pointed the other way:
|
|
54
100
|
|
|
55
101
|
- **Values**: plain data (finite numbers, strings, booleans, `None`,
|
|
56
102
|
lists/dicts of the same) crosses by value; everything else is a live
|
|
@@ -129,9 +175,11 @@ And *which packages* it sees is the working directory's
|
|
|
129
175
|
Run Python in your project, get your project's packages: `npm install`
|
|
130
176
|
next to your program is the whole setup.
|
|
131
177
|
|
|
132
|
-
|
|
133
|
-
tier
|
|
134
|
-
[`examples/js/jsdemo.shcc`](https://github.com/sreekotay/concurrent-c/blob/main/examples/js/jsdemo.shcc)
|
|
178
|
+
Writing Concurrent-C itself rather than Python? The zero-IPC hosted
|
|
179
|
+
tier is `cc_js_new(false, &a)` (needs libnode) —
|
|
180
|
+
[`examples/js/jsdemo.shcc`](https://github.com/sreekotay/concurrent-c/blob/main/examples/js/jsdemo.shcc);
|
|
181
|
+
`cc_js_new(true, &a)` is the same separate-process wire this package
|
|
182
|
+
speaks, from CC.
|
|
135
183
|
|
|
136
184
|
## Publishing
|
|
137
185
|
|
|
@@ -142,36 +190,6 @@ From the Concurrent-C repo root (packs this wheel and the npm sibling):
|
|
|
142
190
|
./scripts/publish_bridges.sh --publish # bump patch, pack, twine + npm publish
|
|
143
191
|
```
|
|
144
192
|
|
|
145
|
-
## Measured
|
|
146
|
-
|
|
147
|
-
From `python -m cc_node.examples.bench_wire` (sources under
|
|
148
|
-
[`cc_node/examples/`](https://github.com/sreekotay/concurrent-c/blob/main/pypi/cc-node/cc_node/examples/))
|
|
149
|
-
on a 4-vCPU x86-64 box, node 22 / python 3.11
|
|
150
|
-
([`perf/baselines/cc_node_bridge_py_20260810.txt`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/cc_node_bridge_py_20260810.txt);
|
|
151
|
-
catalog: [`perf/baselines/README.md`](https://github.com/sreekotay/concurrent-c/blob/main/perf/baselines/README.md)):
|
|
152
|
-
|
|
153
|
-
| what | result |
|
|
154
|
-
|---|---|
|
|
155
|
-
| spawn a domain (node child, first eval) | 28ms |
|
|
156
|
-
| wire round trip (smallest call) | 105µs |
|
|
157
|
-
| Python-callback round trip (JS → Python → JS) | 153µs |
|
|
158
|
-
| 8MB `array('d')` argument, shm spill | **9.5ms** |
|
|
159
|
-
| the same 8MB as a JSON list | 499ms — the spill is **52x** |
|
|
160
|
-
|
|
161
|
-
The wire is strict request/response JSON on dedicated fds — replies
|
|
162
|
-
pair by request id, and stdio stays yours, so `console.log` in
|
|
163
|
-
evaluated JS reaches the real stdout and can never collide with a
|
|
164
|
-
protocol reply — with the shared-memory spill for bulk data (private
|
|
165
|
-
0700 per-bridge directory, 0600 exclusive-create files, removed with
|
|
166
|
-
the bridge). The same discipline concurrent-c-python's isolated
|
|
167
|
-
domains speak, mirrored. True pinned zero-copy leases remain future
|
|
168
|
-
work.
|
|
169
|
-
|
|
170
|
-
One boundary, stated plainly: the domain is **crash isolation, not a
|
|
171
|
-
security sandbox** — the node child inherits your environment and runs
|
|
172
|
-
with your OS privileges, so do not run untrusted JavaScript through
|
|
173
|
-
it.
|
|
174
|
-
|
|
175
193
|
A worked tour (builtin Node modules, chains, callbacks, thenables,
|
|
176
194
|
buffers — no npm install needed):
|
|
177
195
|
`python -m cc_node.examples.use_node`.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "concurrent-c-node"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.12.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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/concurrent_c_node.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{concurrent_c_node-0.10.0 → concurrent_c_node-0.12.0}/concurrent_c_node.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|