denosaurs 0.1.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.
- denosaurs-0.1.0/.github/workflows/benchmarks.yml +32 -0
- denosaurs-0.1.0/.github/workflows/docs.yml +53 -0
- denosaurs-0.1.0/.github/workflows/workflow.yaml +90 -0
- denosaurs-0.1.0/.gitignore +72 -0
- denosaurs-0.1.0/BENCHMARKS.md +68 -0
- denosaurs-0.1.0/CLAUDE.md +472 -0
- denosaurs-0.1.0/Cargo.lock +2727 -0
- denosaurs-0.1.0/Cargo.toml +50 -0
- denosaurs-0.1.0/LICENSE +22 -0
- denosaurs-0.1.0/Makefile +100 -0
- denosaurs-0.1.0/PATCH.md +114 -0
- denosaurs-0.1.0/PKG-INFO +228 -0
- denosaurs-0.1.0/README.md +198 -0
- denosaurs-0.1.0/benches/runtime_benches.rs +90 -0
- denosaurs-0.1.0/benches_py/test_bench_runtime.py +87 -0
- denosaurs-0.1.0/benchmarks/README.md +70 -0
- denosaurs-0.1.0/benchmarks/bench_memory.py +105 -0
- denosaurs-0.1.0/benchmarks/bench_regex.py +86 -0
- denosaurs-0.1.0/benchmarks/bench_startup.py +56 -0
- denosaurs-0.1.0/benchmarks/bench_threading.py +71 -0
- denosaurs-0.1.0/benchmarks/suite.py +102 -0
- denosaurs-0.1.0/docs/api/config.md +3 -0
- denosaurs-0.1.0/docs/api/denosaurs.md +14 -0
- denosaurs-0.1.0/docs/api/runtime.md +3 -0
- denosaurs-0.1.0/docs/api/types.md +17 -0
- denosaurs-0.1.0/docs/assets/banner.png +0 -0
- denosaurs-0.1.0/docs/assets/logo.png +0 -0
- denosaurs-0.1.0/docs/assets/logo.svg +4 -0
- denosaurs-0.1.0/docs/concepts/evaluation.md +282 -0
- denosaurs-0.1.0/docs/concepts/runtime.md +291 -0
- denosaurs-0.1.0/docs/concepts/types.md +275 -0
- denosaurs-0.1.0/docs/contributing/architecture.md +367 -0
- denosaurs-0.1.0/docs/contributing/development.md +66 -0
- denosaurs-0.1.0/docs/guides/advanced/inspector.md +63 -0
- denosaurs-0.1.0/docs/guides/advanced/snapshots.md +206 -0
- denosaurs-0.1.0/docs/guides/advanced/webassembly.md +80 -0
- denosaurs-0.1.0/docs/guides/bindings.md +283 -0
- denosaurs-0.1.0/docs/guides/modules.md +270 -0
- denosaurs-0.1.0/docs/index.md +47 -0
- denosaurs-0.1.0/docs/quickstart.md +116 -0
- denosaurs-0.1.0/docs/stubs/denosaurs/__init__.py +68 -0
- denosaurs-0.1.0/docs/stubs/denosaurs/_denosaurs.py +1002 -0
- denosaurs-0.1.0/docs/stylesheets/extra.css +6 -0
- denosaurs-0.1.0/docs/use-cases/ai-agent.md +211 -0
- denosaurs-0.1.0/docs/use-cases/playground.md +100 -0
- denosaurs-0.1.0/docs/use-cases/plugin-system.md +177 -0
- denosaurs-0.1.0/docs/use-cases/serverless-runtime.md +259 -0
- denosaurs-0.1.0/docs/use-cases/workflow.md +226 -0
- denosaurs-0.1.0/examples/README.md +69 -0
- denosaurs-0.1.0/examples/add.wasm +0 -0
- denosaurs-0.1.0/examples/basic_eval.py +57 -0
- denosaurs-0.1.0/examples/bindings_async.py +121 -0
- denosaurs-0.1.0/examples/bindings_basic.py +232 -0
- denosaurs-0.1.0/examples/context_local_api.py +166 -0
- denosaurs-0.1.0/examples/fastapi_multitenant.py +172 -0
- denosaurs-0.1.0/examples/inspector.py +48 -0
- denosaurs-0.1.0/examples/markdown_parser.py +86 -0
- denosaurs-0.1.0/examples/modules_basic.py +43 -0
- denosaurs-0.1.0/examples/modules_wasm.py +41 -0
- denosaurs-0.1.0/examples/resource_limits.py +292 -0
- denosaurs-0.1.0/examples/snapshot_example.py +245 -0
- denosaurs-0.1.0/examples/threading_gil.py +81 -0
- denosaurs-0.1.0/examples/type_conversion.py +280 -0
- denosaurs-0.1.0/mkdocs.yml +108 -0
- denosaurs-0.1.0/pyproject.toml +60 -0
- denosaurs-0.1.0/python/denosaurs/__init__.py +257 -0
- denosaurs-0.1.0/python/denosaurs/__main__.py +63 -0
- denosaurs-0.1.0/python/denosaurs/_denosaurs.pyi +1002 -0
- denosaurs-0.1.0/python/denosaurs/py.typed +0 -0
- denosaurs-0.1.0/src/lib.rs +42 -0
- denosaurs-0.1.0/src/runtime/config.rs +574 -0
- denosaurs-0.1.0/src/runtime/conversion.rs +375 -0
- denosaurs-0.1.0/src/runtime/error.rs +271 -0
- denosaurs-0.1.0/src/runtime/handle.rs +822 -0
- denosaurs-0.1.0/src/runtime/inspector.rs +515 -0
- denosaurs-0.1.0/src/runtime/js_value.rs +448 -0
- denosaurs-0.1.0/src/runtime/loader.rs +399 -0
- denosaurs-0.1.0/src/runtime/mod.rs +179 -0
- denosaurs-0.1.0/src/runtime/ops.rs +520 -0
- denosaurs-0.1.0/src/runtime/python/bridge.rs +220 -0
- denosaurs-0.1.0/src/runtime/python/error.rs +94 -0
- denosaurs-0.1.0/src/runtime/python/mod.rs +73 -0
- denosaurs-0.1.0/src/runtime/python/runtime.rs +1048 -0
- denosaurs-0.1.0/src/runtime/python/snapshot.rs +49 -0
- denosaurs-0.1.0/src/runtime/python/stats.rs +153 -0
- denosaurs-0.1.0/src/runtime/python/utils.rs +58 -0
- denosaurs-0.1.0/src/runtime/runner.rs +3253 -0
- denosaurs-0.1.0/src/runtime/snapshot.rs +100 -0
- denosaurs-0.1.0/src/runtime/stats.rs +241 -0
- denosaurs-0.1.0/src/runtime/stream.rs +533 -0
- denosaurs-0.1.0/tests/test_denosaurs_api.py +341 -0
- denosaurs-0.1.0/tests/test_function.py +195 -0
- denosaurs-0.1.0/tests/test_modules.py +274 -0
- denosaurs-0.1.0/tests/test_ops.py +642 -0
- denosaurs-0.1.0/tests/test_runtime.py +1880 -0
- denosaurs-0.1.0/tests/test_termination_handle.py +132 -0
- denosaurs-0.1.0/uv.lock +859 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Benchmarks
|
|
2
|
+
|
|
3
|
+
# Informational only -- reports numbers in the log/summary, never fails the build.
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
pull_request:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
benchmarks:
|
|
14
|
+
# macos-latest: the Linux cdylib build currently fails to link V8 (rust-lld
|
|
15
|
+
# TLS relocation vs -shared, tracked separately, pre-existing/unrelated to
|
|
16
|
+
# benchmarking) -- same failure as the v0.1.0 Linux wheel build.
|
|
17
|
+
runs-on: macos-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v5
|
|
20
|
+
|
|
21
|
+
- uses: astral-sh/setup-uv@v7
|
|
22
|
+
|
|
23
|
+
- name: Rust benchmarks (Criterion)
|
|
24
|
+
run: cargo bench --features bench | tee -a "$GITHUB_STEP_SUMMARY"
|
|
25
|
+
|
|
26
|
+
- name: Build release extension
|
|
27
|
+
run: |
|
|
28
|
+
uv sync --group all
|
|
29
|
+
uv run maturin develop --uv --release
|
|
30
|
+
|
|
31
|
+
- name: Python benchmarks (pytest-benchmark)
|
|
32
|
+
run: uv run pytest benches_py/ --benchmark-only | tee -a "$GITHUB_STEP_SUMMARY"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
# push:
|
|
5
|
+
# branches:
|
|
6
|
+
# - main
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
pages: write
|
|
13
|
+
id-token: write
|
|
14
|
+
|
|
15
|
+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
|
16
|
+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
|
17
|
+
concurrency:
|
|
18
|
+
group: "pages"
|
|
19
|
+
cancel-in-progress: false
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
build:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v5
|
|
26
|
+
|
|
27
|
+
- uses: actions/setup-python@v6
|
|
28
|
+
with:
|
|
29
|
+
python-version: "3.x"
|
|
30
|
+
|
|
31
|
+
- uses: astral-sh/setup-uv@v7
|
|
32
|
+
|
|
33
|
+
- name: Install dependencies
|
|
34
|
+
run: uv sync --no-install-project --group docs
|
|
35
|
+
|
|
36
|
+
- name: Build documentation
|
|
37
|
+
run: source .venv/bin/activate && mkdocs build
|
|
38
|
+
|
|
39
|
+
- name: Upload artifact
|
|
40
|
+
uses: actions/upload-pages-artifact@v4
|
|
41
|
+
with:
|
|
42
|
+
path: ./site
|
|
43
|
+
|
|
44
|
+
deploy:
|
|
45
|
+
environment:
|
|
46
|
+
name: github-pages
|
|
47
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
needs: build
|
|
50
|
+
steps:
|
|
51
|
+
- name: Deploy to GitHub Pages
|
|
52
|
+
id: deployment
|
|
53
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Runs only when a GitHub Release is published -- never on every push.
|
|
4
|
+
# Actually publishing requires PyPI Trusted Publishing to be configured for
|
|
5
|
+
# this exact repo + workflow on the PyPI project page first (see README).
|
|
6
|
+
on:
|
|
7
|
+
release:
|
|
8
|
+
types: [published]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
linux:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
target: [x86_64]
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v5
|
|
21
|
+
- name: Build manylinux wheels
|
|
22
|
+
uses: PyO3/maturin-action@v1
|
|
23
|
+
with:
|
|
24
|
+
target: ${{ matrix.target }}
|
|
25
|
+
args: --release --out dist --find-interpreter
|
|
26
|
+
# v8 >=150.1 (pulled in via deno_core >=0.409, see Cargo.toml) needs
|
|
27
|
+
# glibc's memfd_create (glibc >=2.27), which manylinux2014's glibc
|
|
28
|
+
# 2.17 lacks ("auto" resolved to manylinux2014 and the resulting
|
|
29
|
+
# wheel failed to import: "undefined symbol: memfd_create").
|
|
30
|
+
# manylinux_2_28 ships glibc 2.28.
|
|
31
|
+
manylinux: 2_28
|
|
32
|
+
- uses: actions/upload-artifact@v4
|
|
33
|
+
with:
|
|
34
|
+
name: wheels-linux-${{ matrix.target }}
|
|
35
|
+
path: dist
|
|
36
|
+
|
|
37
|
+
macos:
|
|
38
|
+
runs-on: macos-latest
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v5
|
|
41
|
+
- uses: PyO3/maturin-action@v1
|
|
42
|
+
with:
|
|
43
|
+
args: --release --out dist --find-interpreter
|
|
44
|
+
- uses: actions/upload-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: wheels-macos
|
|
47
|
+
path: dist
|
|
48
|
+
|
|
49
|
+
windows:
|
|
50
|
+
runs-on: windows-latest
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v5
|
|
53
|
+
- uses: PyO3/maturin-action@v1
|
|
54
|
+
with:
|
|
55
|
+
args: --release --out dist --find-interpreter
|
|
56
|
+
- uses: actions/upload-artifact@v4
|
|
57
|
+
with:
|
|
58
|
+
name: wheels-windows
|
|
59
|
+
path: dist
|
|
60
|
+
|
|
61
|
+
sdist:
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/checkout@v5
|
|
65
|
+
- uses: PyO3/maturin-action@v1
|
|
66
|
+
with:
|
|
67
|
+
command: sdist
|
|
68
|
+
args: --out dist
|
|
69
|
+
- uses: actions/upload-artifact@v4
|
|
70
|
+
with:
|
|
71
|
+
name: wheels-sdist
|
|
72
|
+
path: dist
|
|
73
|
+
|
|
74
|
+
publish:
|
|
75
|
+
name: Publish to PyPI (Trusted Publishing)
|
|
76
|
+
needs: [linux, macos, windows, sdist]
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
environment:
|
|
79
|
+
name: pypi
|
|
80
|
+
url: https://pypi.org/p/denosaurs
|
|
81
|
+
permissions:
|
|
82
|
+
id-token: write # required for PyPI Trusted Publishing (OIDC) -- no API token secret needed
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/download-artifact@v6
|
|
85
|
+
with:
|
|
86
|
+
pattern: wheels-*
|
|
87
|
+
path: dist
|
|
88
|
+
merge-multiple: true
|
|
89
|
+
- name: Publish
|
|
90
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/target
|
|
2
|
+
|
|
3
|
+
# Byte-compiled / optimized / DLL files
|
|
4
|
+
__pycache__/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
.venv/
|
|
14
|
+
env/
|
|
15
|
+
bin/
|
|
16
|
+
build/
|
|
17
|
+
develop-eggs/
|
|
18
|
+
dist/
|
|
19
|
+
eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
include/
|
|
26
|
+
man/
|
|
27
|
+
venv/
|
|
28
|
+
*.egg-info/
|
|
29
|
+
.installed.cfg
|
|
30
|
+
*.egg
|
|
31
|
+
|
|
32
|
+
# Installer logs
|
|
33
|
+
pip-log.txt
|
|
34
|
+
pip-delete-this-directory.txt
|
|
35
|
+
pip-selfcheck.json
|
|
36
|
+
|
|
37
|
+
# Unit test / coverage reports
|
|
38
|
+
htmlcov/
|
|
39
|
+
.tox/
|
|
40
|
+
.coverage
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
|
|
45
|
+
# Translations
|
|
46
|
+
*.mo
|
|
47
|
+
|
|
48
|
+
# Mr Developer
|
|
49
|
+
.mr.developer.cfg
|
|
50
|
+
.project
|
|
51
|
+
.pydevproject
|
|
52
|
+
|
|
53
|
+
# Rope
|
|
54
|
+
.ropeproject
|
|
55
|
+
|
|
56
|
+
# Django stuff:
|
|
57
|
+
*.log
|
|
58
|
+
*.pot
|
|
59
|
+
|
|
60
|
+
.DS_Store
|
|
61
|
+
|
|
62
|
+
# Sphinx documentation
|
|
63
|
+
docs/_build/
|
|
64
|
+
|
|
65
|
+
# PyCharm
|
|
66
|
+
.idea/
|
|
67
|
+
|
|
68
|
+
# VSCode
|
|
69
|
+
.vscode/
|
|
70
|
+
|
|
71
|
+
# Pyenv
|
|
72
|
+
.python-version
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Benchmarks
|
|
2
|
+
|
|
3
|
+
Two suites: Rust-level (Criterion, `benches/`, bypasses the Python API) and
|
|
4
|
+
Python-level (pytest-benchmark, `benches_py/`, the real user-facing surface).
|
|
5
|
+
Both run in CI on every push/PR (`.github/workflows/benchmarks.yml`),
|
|
6
|
+
informational only -- they report numbers, they don't gate merges.
|
|
7
|
+
|
|
8
|
+
Numbers below are one real measured run, not simulated. They are
|
|
9
|
+
environment-dependent -- re-run locally before trusting them for a regression
|
|
10
|
+
decision on different hardware.
|
|
11
|
+
|
|
12
|
+
## Measurement environment
|
|
13
|
+
|
|
14
|
+
- Apple M2, 8 cores, 16 GB RAM, macOS 25.5.0 (Darwin), arm64
|
|
15
|
+
- Rust 1.93.1, `cargo bench --features bench` (release/`bench` profile)
|
|
16
|
+
- Python 3.14.3, `pytest-benchmark` 5.3.0, `maturin develop --release`
|
|
17
|
+
|
|
18
|
+
## Rust (Criterion, `cargo bench --features bench`)
|
|
19
|
+
|
|
20
|
+
| Benchmark | Time |
|
|
21
|
+
|---|---|
|
|
22
|
+
| `isolate_creation_and_close` | 2.52 ms |
|
|
23
|
+
| `simple_eval_throughput` (`1 + 41`) | 4.20 µs |
|
|
24
|
+
| `host_callback_op_dispatch` (real Python callable via `register_op`) | 13.14 µs |
|
|
25
|
+
| `termination_handle/is_terminated_check` | 0.92 ns |
|
|
26
|
+
| `termination_handle/terminate_round_trip` (idle runtime) | 87.16 µs |
|
|
27
|
+
|
|
28
|
+
`is_terminated()` is a single atomic load -- effectively free to poll. The
|
|
29
|
+
206x-larger `terminate_round_trip` number is the cost of the full path:
|
|
30
|
+
requesting termination, calling `v8::IsolateHandle::terminate_execution()`,
|
|
31
|
+
and waiting for the runtime thread to acknowledge shutdown.
|
|
32
|
+
|
|
33
|
+
## Python (`pytest-benchmark`, `pytest benches_py/ --benchmark-only`)
|
|
34
|
+
|
|
35
|
+
| Benchmark | Mean |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `test_cold_start` (new `Runtime()` + one eval) | 2.82 ms |
|
|
38
|
+
| `test_steady_state_100_evals` (100 sequential evals, warm runtime) | 363.25 µs total (~3.63 µs/eval) |
|
|
39
|
+
| `test_steady_state_1000_evals` (1000 sequential evals, warm runtime) | 3.46 ms total (~3.46 µs/eval) |
|
|
40
|
+
| `test_host_callback_round_trip` (`bind_function` + call from JS) | 13.98 µs |
|
|
41
|
+
| `test_normal_completing_eval_baseline` | 3.77 µs |
|
|
42
|
+
| `test_watchdog_termination_overhead` | 59.62 ms |
|
|
43
|
+
|
|
44
|
+
Per-eval cost at the Python layer (~3.5-3.8 µs) matches the Rust-level
|
|
45
|
+
`simple_eval_throughput` number closely -- the Python binding adds negligible
|
|
46
|
+
overhead over the raw `RuntimeHandle`.
|
|
47
|
+
|
|
48
|
+
### Watchdog-termination proof, timed precisely
|
|
49
|
+
|
|
50
|
+
`test_watchdog_termination_overhead` runs the exact scenario in
|
|
51
|
+
`tests/test_termination_handle.py`: a runaway `while(true){}` eval, killed
|
|
52
|
+
from a separate watchdog thread via `TerminationHandle.terminate()`, but with
|
|
53
|
+
the watchdog's sleep shortened to 50 ms (20 rounds) so the suite stays fast.
|
|
54
|
+
Measured mean: 59.62 ms. Subtracting the artificial 50 ms delay leaves
|
|
55
|
+
**~9.6 ms** of real overhead for the cross-thread termination path itself
|
|
56
|
+
(watchdog wakes up, calls into V8's isolate handle from a foreign thread,
|
|
57
|
+
the runtime thread unwinds and returns control to Python) -- consistent with
|
|
58
|
+
the Rust-level `terminate_round_trip` number once you add Python's own
|
|
59
|
+
call/exception overhead on top.
|
|
60
|
+
|
|
61
|
+
## Reproducing
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
cargo bench --features bench
|
|
65
|
+
uv sync --group all
|
|
66
|
+
uv run maturin develop --uv --release
|
|
67
|
+
uv run pytest benches_py/ --benchmark-only
|
|
68
|
+
```
|