@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@torrent-tv/proxy",
3
- "version": "2.97.1",
3
+ "version": "2.97.2",
4
4
  "description": "Torrent proxy client that exposes webseed-like HTTP stream endpoint.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "repository": {
@@ -16,7 +16,7 @@
16
16
  * process figure alone is said.
17
17
  */
18
18
 
19
- import { readFile, readdir } from "node:fs/promises";
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 {Promise<{ main: number, worker: number, other: number } | null>}
87
+ * @returns {{ main: number, worker: number, other: number } | null}
67
88
  */
68
- export async function readThreadSeconds(pid = process.pid) {
89
+ export function readThreadSeconds(pid = process.pid) {
69
90
  let tids;
70
91
  try {
71
- tids = await readdir(`/proc/${pid}/task`);
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
- await Promise.all(tids.map(async (entry) => {
77
- const tid = Number(entry);
78
- const stat = await readFile(`/proc/${pid}/task/${entry}/stat`, "utf8").then(parseStat, () => null);
79
- if (stat) parts[partOfThread(tid, stat.name, pid)] += stat.seconds;
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 {Promise<Map<number, number>>}
108
+ * @returns {Map<number, number>}
89
109
  */
90
- export async function readProcessesSeconds(pids) {
110
+ export function readProcessesSeconds(pids) {
91
111
  const seconds = new Map();
92
- await Promise.all(pids.map(async (pid) => {
93
- const stat = await readFile(`/proc/${pid}/stat`, "utf8").then(parseStat, () => null);
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
- let reading = false;
162
- const tick = async () => {
163
- if (reading) return;
164
- reading = true;
165
- try {
166
- const usage = process.cpuUsage();
167
- const [threads, ffmpeg] = await Promise.all([readThreadSeconds(), readProcessesSeconds(ffmpegPids())]);
168
- const now = { at: Date.now(), process: (usage.user + usage.system) / 1e6, threads, ffmpeg };
169
- const shares = previous ? sharesBetween(previous, now) : null;
170
- previous = now;
171
- if (!shares) return;
172
- series.push(shares);
173
- if (detailed()) log(`processor: ${describeShares([shares])}`);
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(() => { void tick(); }, everyMs);
196
+ const timer = setInterval(tick, everyMs);
184
197
  if (typeof timer.unref === "function") timer.unref();
185
198
  return { stop: () => clearInterval(timer) };
186
199
  }