@torrent-tv/proxy 2.97.1 → 2.97.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/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* process figure alone is said.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
20
20
|
|
|
21
21
|
/** Clock ticks per second of `/proc/<pid>/stat`, as in `encode/host-load.js`. */
|
|
22
22
|
const CLOCK_TICKS_PER_SECOND = 100;
|
|
@@ -58,26 +58,46 @@ export function partOfThread(tid, name, pid) {
|
|
|
58
58
|
return "other";
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* One `/proc` stat file, or null when it cannot be read.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} file
|
|
65
|
+
* @returns {{ name: string, seconds: number } | null}
|
|
66
|
+
*/
|
|
67
|
+
function statOf(file) {
|
|
68
|
+
try {
|
|
69
|
+
return parseStat(readFileSync(file, "utf8"));
|
|
70
|
+
} catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
61
75
|
/**
|
|
62
76
|
* CPU seconds of this process's threads, by part, or null where `/proc` cannot
|
|
63
77
|
* be read.
|
|
64
78
|
*
|
|
79
|
+
* READ SYNCHRONOUSLY, with the clock read beside it: a reading is only a share
|
|
80
|
+
* when every counter in it and its time belong to one instant. Read as
|
|
81
|
+
* promises on the field host (2.97.0), the counters were taken while the main
|
|
82
|
+
* thread was busy and the time after, and a second read "process 1238 %" of a
|
|
83
|
+
* core (torrent-tv/meta#177). About a hundred small files a second, kernel
|
|
84
|
+
* memory, no disk.
|
|
85
|
+
*
|
|
65
86
|
* @param {number} [pid]
|
|
66
|
-
* @returns {
|
|
87
|
+
* @returns {{ main: number, worker: number, other: number } | null}
|
|
67
88
|
*/
|
|
68
|
-
export
|
|
89
|
+
export function readThreadSeconds(pid = process.pid) {
|
|
69
90
|
let tids;
|
|
70
91
|
try {
|
|
71
|
-
tids =
|
|
92
|
+
tids = readdirSync(`/proc/${pid}/task`);
|
|
72
93
|
} catch {
|
|
73
94
|
return null;
|
|
74
95
|
}
|
|
75
96
|
const parts = { main: 0, worker: 0, other: 0 };
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}));
|
|
97
|
+
for (const entry of tids) {
|
|
98
|
+
const stat = statOf(`/proc/${pid}/task/${entry}/stat`);
|
|
99
|
+
if (stat) parts[partOfThread(Number(entry), stat.name, pid)] += stat.seconds;
|
|
100
|
+
}
|
|
81
101
|
return parts;
|
|
82
102
|
}
|
|
83
103
|
|
|
@@ -85,14 +105,14 @@ export async function readThreadSeconds(pid = process.pid) {
|
|
|
85
105
|
* CPU seconds of each of these processes that can be read now.
|
|
86
106
|
*
|
|
87
107
|
* @param {number[]} pids
|
|
88
|
-
* @returns {
|
|
108
|
+
* @returns {Map<number, number>}
|
|
89
109
|
*/
|
|
90
|
-
export
|
|
110
|
+
export function readProcessesSeconds(pids) {
|
|
91
111
|
const seconds = new Map();
|
|
92
|
-
|
|
93
|
-
const stat =
|
|
112
|
+
for (const pid of pids) {
|
|
113
|
+
const stat = statOf(`/proc/${pid}/stat`);
|
|
94
114
|
if (stat) seconds.set(pid, stat.seconds);
|
|
95
|
-
}
|
|
115
|
+
}
|
|
96
116
|
return seconds;
|
|
97
117
|
}
|
|
98
118
|
|
|
@@ -158,29 +178,22 @@ export function startProcessorReport({ log, ffmpegPids, detailed = () => false,
|
|
|
158
178
|
let previous = null;
|
|
159
179
|
let series = [];
|
|
160
180
|
let since = Date.now();
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
series
|
|
173
|
-
|
|
174
|
-
if (now.at - since >= sayEveryMs) {
|
|
175
|
-
log(`processor: ${describeShares(series)}`);
|
|
176
|
-
series = [];
|
|
177
|
-
since = now.at;
|
|
178
|
-
}
|
|
179
|
-
} finally {
|
|
180
|
-
reading = false;
|
|
181
|
+
const tick = () => {
|
|
182
|
+
const at = Date.now();
|
|
183
|
+
const usage = process.cpuUsage();
|
|
184
|
+
const now = { at, process: (usage.user + usage.system) / 1e6, threads: readThreadSeconds(), ffmpeg: readProcessesSeconds(ffmpegPids()) };
|
|
185
|
+
const shares = previous ? sharesBetween(previous, now) : null;
|
|
186
|
+
previous = now;
|
|
187
|
+
if (!shares) return;
|
|
188
|
+
series.push(shares);
|
|
189
|
+
if (detailed()) log(`processor: ${describeShares([shares])}`);
|
|
190
|
+
if (now.at - since >= sayEveryMs) {
|
|
191
|
+
log(`processor: ${describeShares(series)}`);
|
|
192
|
+
series = [];
|
|
193
|
+
since = now.at;
|
|
181
194
|
}
|
|
182
195
|
};
|
|
183
|
-
const timer = setInterval(
|
|
196
|
+
const timer = setInterval(tick, everyMs);
|
|
184
197
|
if (typeof timer.unref === "function") timer.unref();
|
|
185
198
|
return { stop: () => clearInterval(timer) };
|
|
186
199
|
}
|