Skip to content

Commit c30b57f

Browse files
committed
Add CPU usage input with pull streams
1 parent c63ca11 commit c30b57f

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
module src/lib/resource_utilization_input
2+
3+
import src/lib/event
4+
import src/lib/timestamp
5+
import io/time
6+
7+
/*
8+
* FFI to get cpu usage from node js backend
9+
* Only works with node js backend
10+
*/
11+
12+
/// Get the current CPU usage as a percentage (0.0 to 1.0)
13+
/// This function samples CPU times, waits a short interval internally (50ms),
14+
/// and returns the usage fraction for that interval. The wait is non-blocking.
15+
///
16+
/// This function only works on the jsNode backend.
17+
extern def getCpuUsage() at async: Double =
18+
jsNode """$effekt.capture(k => {
19+
const os = require('os');
20+
function sample() {
21+
const cpus = os.cpus();
22+
let totalIdle = 0;
23+
let totalTick = 0;
24+
cpus.forEach(cpu => {
25+
for (const type in cpu.times) {
26+
totalTick += cpu.times[type];
27+
}
28+
totalIdle += cpu.times.idle;
29+
});
30+
return { totalIdle, totalTick };
31+
}
32+
33+
const s1 = sample();
34+
const interval = 50; // milliseconds; smaller = more noise, larger = smoother
35+
36+
setTimeout(() => {
37+
const s2 = sample();
38+
const idleDiff = s2.totalIdle - s1.totalIdle;
39+
const totalDiff = s2.totalTick - s1.totalTick;
40+
let usage = 0;
41+
if (totalDiff > 0) {
42+
usage = 1 - (idleDiff / totalDiff);
43+
if (usage < 0) usage = 0;
44+
if (usage > 1) usage = 1;
45+
}
46+
k(usage);
47+
}, interval);
48+
})"""
49+
50+
/// Infinite pull stream that yields CPU usage events
51+
def cpuUsagePullStream() { body: () => Unit / { read[Event] } }: Unit = {
52+
try body() with read[Event] {
53+
resume {
54+
val cpuUsage = getCpuUsage()
55+
val timestamp = currentTimestampMillis()
56+
cpuUsage.toEvent(timestamp)
57+
}
58+
}
59+
}
60+
61+
/// Pull stream that yields at most `limit` CPU usage events
62+
def cpuUsagePullStream(limit: Int) { body: () => Unit / { read[Event] } }: Unit = {
63+
var count = 0
64+
try body() with read[Event] {
65+
resume {
66+
if (count >= limit) {
67+
do stop()
68+
} else {
69+
count = count + 1
70+
}
71+
val cpuUsage = getCpuUsage()
72+
val timestamp = currentTimestampMillis()
73+
cpuUsage.toEvent(timestamp)
74+
}
75+
}
76+
}
77+
78+
namespace examples {
79+
def example1(): Unit = {
80+
with boundary
81+
var i = 0
82+
cpuUsagePullStream() {
83+
while (i < 10) {
84+
println("CPU Usage Event received: " ++ do read[Event]().show())
85+
i = i + 1
86+
time::sleep(500)
87+
}
88+
}
89+
}
90+
91+
def main() = {
92+
example1()
93+
}
94+
}

0 commit comments

Comments
 (0)