@ai-ecoverse/slicc-kernel 1.124.1 → 1.124.2
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.
- package/README.md +5 -2
- package/dist/kernel-worker.js +45 -10
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +4 -2
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +45 -10
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +4 -2
- package/dist/process-worker.js.map +2 -2
- package/dist/types/kernel/proc-info.d.ts +2 -0
- package/dist/types/kernel/wasm-memories.d.ts +8 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -942,11 +942,14 @@ The kernel writes `/etc/passwd` and `/etc/group` when it starts (see [Users](#us
|
|
|
942
942
|
### How many processes at once
|
|
943
943
|
|
|
944
944
|
In a browser every process worker of the page shares one renderer. V8 reserves about 8 GiB of address space for each 32-bit wasm memory, whatever its declared maximum, and its sandbox holds about 1 TiB. So a page runs about 125 wasm processes (or programs that own a wasm memory) at once, counting everything in the renderer (#970). Node has no such ceiling, and neither does Linux. The kernel keeps processes inside that ceiling:
|
|
945
|
-
- **The ceiling:** 112 by default in a browser and none in Node. It's the kernel's count of live wasm processes, with the kernel's other wasm memories in the page left outside it. When an instantiation runs out of memory anyway, the kernel learns the real ceiling at that moment (the live count minus one), and that learned value wins over the default.
|
|
945
|
+
- **The ceiling:** 112 by default in a browser and none in Node. It's the kernel's count of live wasm processes, with the kernel's other wasm memories in the page left outside it. When an instantiation runs out of memory anyway, the kernel learns the real ceiling at that moment (the live count minus one), and that learned value wins over the default. A learned ceiling is never below 16, since an OOM at a low count means something outside it (another tab in the same renderer) filled the renderer. It's raised by 8 for each minute without another OOM, back to the default.
|
|
946
946
|
- **Admission:** a spawn, fork, exec or `kernel.run` at the ceiling waits for another process to exit. It keeps waiting as long as processes exit or are admitted, and fails with `EAGAIN` only after 10 s with neither. A long `make -j` or `xargs -P` therefore queues, and a pipeline that needs more live processes than the ceiling fails cleanly. bash's own retry on a fork's `EAGAIN` (`fork: retry: Resource temporarily unavailable`) handles the rest.
|
|
947
947
|
- **Close to the ceiling** (within 16 of it), the kernel waits for each new process to finish instantiating before the spawn returns. If it ran out of memory, the kernel starts it again, quietly, once there's room, so the caller sees no failure.
|
|
948
948
|
- **The rare residual case:** a process that fails to instantiate with nobody waiting on it, which happens only when something outside the count fills the renderer. It ends with status 126 and `<program>: cannot allocate memory for a new process (too many processes at once)` on its stderr, never a JS `RangeError`.
|
|
949
|
-
-
|
|
949
|
+
- **Below a learned ceiling,** a process that still runs out of memory is started again once another process exits, and the spawn fails with `EAGAIN` after 10 s with none.
|
|
950
|
+
- **`/proc/sys/kernel/slicc_wasm_memories`** reads `<live> <ceiling> <source>`. The source is `default`, `learned`, or `none` (with the ceiling 0).
|
|
951
|
+
|
|
952
|
+
`/proc/sys/kernel/slicc_shared_root` reads `1` while another kernel shares the root (a tab, or a second kernel in the page) and `0` otherwise. A peer's tab that closes is noticed when this kernel next writes to a shared file, at most every 30 s, so the value can stay `1` for a while after a peer has gone.
|
|
950
953
|
|
|
951
954
|
### Metadata
|
|
952
955
|
|
package/dist/kernel-worker.js
CHANGED
|
@@ -6565,7 +6565,7 @@ function satisfies(version, range2) {
|
|
|
6565
6565
|
}
|
|
6566
6566
|
|
|
6567
6567
|
// src/version.ts
|
|
6568
|
-
var KERNEL_VERSION = true ? "1.124.
|
|
6568
|
+
var KERNEL_VERSION = true ? "1.124.2" : "0.0.0-dev";
|
|
6569
6569
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6570
6570
|
function procVersion() {
|
|
6571
6571
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -12721,7 +12721,9 @@ var SYS_TREE = {
|
|
|
12721
12721
|
osrelease: `${OS_RELEASE}
|
|
12722
12722
|
`,
|
|
12723
12723
|
ostype: "Linux\n",
|
|
12724
|
-
slicc_wasm_memories: (listing) => `${listing.wasm?.live ?? 0} ${listing.wasm?.ceiling ?? 0}
|
|
12724
|
+
slicc_wasm_memories: (listing) => `${listing.wasm?.live ?? 0} ${listing.wasm?.ceiling ?? 0} ${listing.wasm?.source ?? "none"}
|
|
12725
|
+
`,
|
|
12726
|
+
slicc_shared_root: (listing) => `${listing.peers ?? 0}
|
|
12725
12727
|
`
|
|
12726
12728
|
}
|
|
12727
12729
|
};
|
|
@@ -21926,37 +21928,65 @@ var SettlingChildren = class {
|
|
|
21926
21928
|
|
|
21927
21929
|
// src/kernel/wasm-memories.ts
|
|
21928
21930
|
var DEFAULT_CEILING = 112;
|
|
21931
|
+
var CEILING_FLOOR = 16;
|
|
21929
21932
|
var IDLE_MS = 1e4;
|
|
21930
21933
|
var MARGIN = 16;
|
|
21934
|
+
var DECAY_MS = 6e4;
|
|
21935
|
+
var DECAY_STEP = 8;
|
|
21931
21936
|
var WasmMemories = class {
|
|
21932
21937
|
live = 0;
|
|
21933
|
-
|
|
21938
|
+
learned;
|
|
21934
21939
|
waiters = /* @__PURE__ */ new Set();
|
|
21940
|
+
base;
|
|
21935
21941
|
idleMs;
|
|
21936
|
-
|
|
21937
|
-
|
|
21942
|
+
now;
|
|
21943
|
+
constructor(ceiling, idleMs = IDLE_MS, now = Date.now) {
|
|
21944
|
+
this.base = ceiling;
|
|
21938
21945
|
this.idleMs = idleMs;
|
|
21946
|
+
this.now = now;
|
|
21947
|
+
}
|
|
21948
|
+
ceiling() {
|
|
21949
|
+
const learned = this.learned;
|
|
21950
|
+
if (!learned) return this.base;
|
|
21951
|
+
const steps = Math.floor((this.now() - learned.at) / DECAY_MS);
|
|
21952
|
+
const raised = learned.ceiling + steps * DECAY_STEP;
|
|
21953
|
+
if (raised < (this.base ?? DEFAULT_CEILING)) return raised;
|
|
21954
|
+
this.learned = void 0;
|
|
21955
|
+
return this.base;
|
|
21939
21956
|
}
|
|
21940
21957
|
count() {
|
|
21941
|
-
|
|
21958
|
+
const ceiling = this.ceiling();
|
|
21959
|
+
const source = this.learned ? "learned" : ceiling === void 0 ? "none" : "default";
|
|
21960
|
+
return { live: this.live, ceiling: ceiling ?? 0, source };
|
|
21942
21961
|
}
|
|
21943
21962
|
ended() {
|
|
21944
21963
|
this.live = Math.max(0, this.live - 1);
|
|
21945
21964
|
this.progress();
|
|
21946
21965
|
}
|
|
21947
21966
|
learn() {
|
|
21948
|
-
|
|
21967
|
+
const top = this.base ?? DEFAULT_CEILING;
|
|
21968
|
+
this.learned = {
|
|
21969
|
+
ceiling: Math.min(top, Math.max(CEILING_FLOOR, this.live - 1)),
|
|
21970
|
+
at: this.now()
|
|
21971
|
+
};
|
|
21949
21972
|
}
|
|
21950
21973
|
near() {
|
|
21951
|
-
|
|
21974
|
+
const ceiling = this.ceiling();
|
|
21975
|
+
return ceiling !== void 0 && this.live + MARGIN >= ceiling;
|
|
21952
21976
|
}
|
|
21953
21977
|
async admit() {
|
|
21954
|
-
|
|
21978
|
+
for (let ceiling = this.ceiling(); ceiling !== void 0 && this.live >= ceiling; ) {
|
|
21955
21979
|
if (!await this.changed()) throw new SpawnError("EAGAIN");
|
|
21980
|
+
ceiling = this.ceiling();
|
|
21956
21981
|
}
|
|
21957
21982
|
this.live += 1;
|
|
21958
21983
|
this.progress();
|
|
21959
21984
|
}
|
|
21985
|
+
async refused() {
|
|
21986
|
+
const ceiling = this.ceiling();
|
|
21987
|
+
if (ceiling === void 0 || this.live >= ceiling) return;
|
|
21988
|
+
if (!await this.changed()) throw new SpawnError("EAGAIN");
|
|
21989
|
+
}
|
|
21960
21990
|
progress() {
|
|
21961
21991
|
const waiters = [...this.waiters];
|
|
21962
21992
|
this.waiters.clear();
|
|
@@ -25217,6 +25247,10 @@ var Launcher = class {
|
|
|
25217
25247
|
return handle;
|
|
25218
25248
|
}
|
|
25219
25249
|
await handle.exited;
|
|
25250
|
+
await this.memories.refused().catch(async (err) => {
|
|
25251
|
+
await fds.closeAll();
|
|
25252
|
+
throw err;
|
|
25253
|
+
});
|
|
25220
25254
|
}
|
|
25221
25255
|
}
|
|
25222
25256
|
start(req) {
|
|
@@ -25282,7 +25316,8 @@ var Launcher = class {
|
|
|
25282
25316
|
processes: this.list(this.credOf(pid)),
|
|
25283
25317
|
load: this.loadAverage(),
|
|
25284
25318
|
cpu: this.cpuTotal(),
|
|
25285
|
-
wasm: this.memories.count()
|
|
25319
|
+
wasm: this.memories.count(),
|
|
25320
|
+
peers: Number(this.locks.shared?.() === true)
|
|
25286
25321
|
}),
|
|
25287
25322
|
sudo: (call, signal) => this.sudo(pid, call, signal),
|
|
25288
25323
|
crontab: (call) => this.crontab(pid, call),
|