jsir 3.0.9 → 3.1.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/deps/room.js +27 -23
- package/deps/util.js +20 -8
- package/package.json +1 -1
package/deps/room.js
CHANGED
|
@@ -17,6 +17,8 @@ const http = require('http');
|
|
|
17
17
|
const tailscalePath = os.platform() === 'darwin' ?
|
|
18
18
|
'/Applications/Tailscale.app/Contents/MacOS/Tailscale':'tailscale';
|
|
19
19
|
const packageJson = require("../package.json");
|
|
20
|
+
const { performance } = require('perf_hooks');
|
|
21
|
+
let elu0 = performance.eventLoopUtilization()
|
|
20
22
|
|
|
21
23
|
async function localConfigs(uniqueNameList) {
|
|
22
24
|
if (uniqueNameList && uniqueNameList.length > 0 ) {
|
|
@@ -373,7 +375,7 @@ async function syncConfigs() {
|
|
|
373
375
|
let configs;
|
|
374
376
|
try {
|
|
375
377
|
configs = await reqFn(setting.configMainFnKey);
|
|
376
|
-
console.$msg(`syncConfigs load ${Object.keys(configs)} files`);
|
|
378
|
+
console.$msg(`syncConfigs load ${Object.keys(configs).length} files`);
|
|
377
379
|
} catch (e) {
|
|
378
380
|
console.$warn("syncConfigs load failed", e)
|
|
379
381
|
return;
|
|
@@ -417,17 +419,14 @@ async function cleanRoom(room) {
|
|
|
417
419
|
}
|
|
418
420
|
|
|
419
421
|
/*
|
|
420
|
-
|
|
421
|
-
|
|
422
|
+
< 0.3 很空
|
|
423
|
+
0.3 ~ 0.6 正常
|
|
424
|
+
0.6 ~ 0.8 明显忙
|
|
422
425
|
*/
|
|
423
426
|
async function getEventLoopDelay() {
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return await timeoutPromise.then(() => {
|
|
428
|
-
const end = process.hrtime.bigint();
|
|
429
|
-
return Number(Math.max(Number(end - start) / 1e4 - (delay * 1e2), 0).toFixed(0)); // 避免负值
|
|
430
|
-
});
|
|
427
|
+
const cur = performance.eventLoopUtilization(elu0); // 计算这段时间的差分
|
|
428
|
+
elu0 = performance.eventLoopUtilization(); // 更新基准点(关键!)
|
|
429
|
+
return Number(cur.utilization.toFixed(1));
|
|
431
430
|
}
|
|
432
431
|
|
|
433
432
|
async function initRoomJsir(room) {
|
|
@@ -457,7 +456,6 @@ async function initRoomJsir(room) {
|
|
|
457
456
|
services[key] = [...new Set(services[key])]
|
|
458
457
|
}
|
|
459
458
|
// 初始化jsir
|
|
460
|
-
let lastJsir = room.jsirs[process.pid]
|
|
461
459
|
setting.selfJsir = {
|
|
462
460
|
pid: process.pid,
|
|
463
461
|
space: setting.defaultSpace,
|
|
@@ -465,7 +463,7 @@ async function initRoomJsir(room) {
|
|
|
465
463
|
obj[key] = getValTips()[index];
|
|
466
464
|
return obj;
|
|
467
465
|
}, {}),
|
|
468
|
-
busy: await getEventLoopDelay()
|
|
466
|
+
busy: await getEventLoopDelay(),
|
|
469
467
|
back: isRunningInBackground(),
|
|
470
468
|
lastUpdateTime: setting.roomTime,
|
|
471
469
|
port: setting.server ? setting.server.address()?.port:null,
|
|
@@ -589,21 +587,27 @@ async function reqNode(node, method, url, port, body) {
|
|
|
589
587
|
}
|
|
590
588
|
|
|
591
589
|
function busyPick(busyItems) {
|
|
592
|
-
if (busyItems.length === 1)
|
|
593
|
-
|
|
590
|
+
if (busyItems.length === 1) return busyItems[0];
|
|
591
|
+
|
|
592
|
+
const weights = busyItems.map(item => {
|
|
593
|
+
// ELU 本来就是 0~1,这里只是兜底
|
|
594
|
+
const busy = Math.min(Math.max(item.busy ?? 1, 0), 1);
|
|
595
|
+
return 1 - busy; // 越忙权重越小
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
const total = weights.reduce((a, b) => a + b, 0);
|
|
599
|
+
if (total <= 0) {
|
|
600
|
+
// 所有节点都接近 1(极忙)时,随机选一个
|
|
601
|
+
return busyItems[Math.floor(Math.random() * busyItems.length)];
|
|
594
602
|
}
|
|
595
|
-
// 反转权重:计算 1 / busy 值作为权重
|
|
596
|
-
const weights = busyItems.map(item => 1 / (item.busy || 1));
|
|
597
|
-
const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
|
|
598
|
-
const random = Math.random() * totalWeight;
|
|
599
603
|
|
|
600
|
-
let
|
|
604
|
+
let r = Math.random() * total;
|
|
601
605
|
for (let i = 0; i < busyItems.length; i++) {
|
|
602
|
-
|
|
603
|
-
if (
|
|
604
|
-
return busyItems[i]; // 选中反转权重命中的对象
|
|
605
|
-
}
|
|
606
|
+
r -= weights[i];
|
|
607
|
+
if (r <= 0) return busyItems[i];
|
|
606
608
|
}
|
|
609
|
+
|
|
610
|
+
return busyItems[busyItems.length - 1]; // 兜底
|
|
607
611
|
}
|
|
608
612
|
|
|
609
613
|
function isMatchTarget(target, node, port) {
|
package/deps/util.js
CHANGED
|
@@ -1608,27 +1608,39 @@ function ei(cmd, args = [], shell = false) {
|
|
|
1608
1608
|
spawnSync(cmd, args, {stdio:"inherit", shell});
|
|
1609
1609
|
}
|
|
1610
1610
|
|
|
1611
|
-
async function eia(cmd, args = [], shell = false) {
|
|
1612
|
-
`
|
|
1613
|
-
当前进程不会卡住,输入输出由cmd进程持有
|
|
1611
|
+
async function eia(cmd, args = [], shell = false, input = null) {
|
|
1614
1612
|
`
|
|
1613
|
+
当前进程不会卡住(事件循环仍在),但会 await 等子进程退出;
|
|
1614
|
+
输入输出默认由 cmd 进程持有;如果传 input,则把 input 写入 stdin。
|
|
1615
|
+
`
|
|
1615
1616
|
if (isRunningInBackground()) {
|
|
1616
1617
|
throw 'Unsupported Operation';
|
|
1617
1618
|
}
|
|
1618
1619
|
setting.enableNextLine = false;
|
|
1619
|
-
|
|
1620
|
+
|
|
1621
|
+
// 如果需要写入 input,则 stdin 必须是 pipe
|
|
1622
|
+
const stdio = input != null
|
|
1623
|
+
? ['pipe', 'inherit', 'inherit']
|
|
1624
|
+
: 'inherit';
|
|
1625
|
+
|
|
1626
|
+
const child = spawn(cmd, args, { stdio, shell });
|
|
1627
|
+
|
|
1628
|
+
// 把内存内容喂给子进程
|
|
1629
|
+
if (input != null) {
|
|
1630
|
+
child.stdin.write(input);
|
|
1631
|
+
child.stdin.end();
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1620
1634
|
return new Promise((resolve, reject) => {
|
|
1621
|
-
// 监听子进程的关闭事件
|
|
1622
1635
|
child.on('close', (code) => {
|
|
1623
1636
|
setting.enableNextLine = true;
|
|
1624
1637
|
resolve(code);
|
|
1625
1638
|
});
|
|
1626
|
-
// 可选:监听子进程的错误事件
|
|
1627
1639
|
child.on('error', (err) => {
|
|
1628
1640
|
setting.enableNextLine = true;
|
|
1629
|
-
reject(err)
|
|
1641
|
+
reject(err);
|
|
1630
1642
|
});
|
|
1631
|
-
})
|
|
1643
|
+
});
|
|
1632
1644
|
}
|
|
1633
1645
|
|
|
1634
1646
|
async function getCbText(mbNum) {
|