feat(animasi): T-0.4 spike lolos — ticker 30 FPS + toast harmonica, CPU idle 2.75% (F-026 awal)
This commit is contained in:
1 parent
b8d2595ca9
commit
e5d5dba023
11 files changed
+501
-12
No files matched your search
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Ukur CPU + output pty binary TUI tia (Phase 0).
|
||||
|
||||
Dipakai untuk spike T-0.4 (docs/spikes/T-0.4-animasi.md):
|
||||
fase 1 animasi 30 FPS menyala, fase 2 setelah tombol 'a' (reduced-motion).
|
||||
|
||||
Pakai:
|
||||
python3 scripts/measure-cpu.py [./tia-love] [detik-per-fase]
|
||||
"""
|
||||
import fcntl
|
||||
import os
|
||||
import pty
|
||||
import signal
|
||||
import struct
|
||||
import sys
|
||||
import termios
|
||||
import threading
|
||||
import time
|
||||
|
||||
BIN = sys.argv[1] if len(sys.argv) > 1 else "./tia-love"
|
||||
SECS = float(sys.argv[2]) if len(sys.argv) > 2 else 8.0
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
pid, fd = pty.fork()
|
||||
if pid == 0:
|
||||
os.chdir(ROOT)
|
||||
os.execvp("timeout", ["timeout", str(int(SECS * 2 + 10)), BIN])
|
||||
fcntl.ioctl(fd, termios.TIOCSWINSZ, struct.pack("HHHH", 40, 120, 0, 0))
|
||||
|
||||
nbytes = [0]
|
||||
|
||||
|
||||
def drain():
|
||||
while True:
|
||||
try:
|
||||
b = os.read(fd, 65536)
|
||||
except OSError:
|
||||
return
|
||||
if not b:
|
||||
return
|
||||
nbytes[0] += len(b)
|
||||
|
||||
|
||||
threading.Thread(target=drain, daemon=True).start()
|
||||
|
||||
|
||||
def app_pid():
|
||||
"""PID anak (binary tia), bukan PID `timeout`."""
|
||||
for _ in range(50):
|
||||
try:
|
||||
kids = open(f"/proc/{pid}/task/{pid}/children").read().split()
|
||||
if kids:
|
||||
return int(kids[0])
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
time.sleep(0.1)
|
||||
return pid
|
||||
|
||||
|
||||
apid = app_pid()
|
||||
print("monitoring PID:", apid)
|
||||
|
||||
HZ = os.sysconf("SC_CLK_TCK")
|
||||
|
||||
|
||||
def cpu():
|
||||
p = open(f"/proc/{apid}/stat").read().split()
|
||||
return (int(p[13]) + int(p[14])) / HZ
|
||||
|
||||
|
||||
def phase(label):
|
||||
b0, c0, t0 = nbytes[0], cpu(), time.time()
|
||||
time.sleep(SECS)
|
||||
b1, c1, t1 = nbytes[0], cpu(), time.time()
|
||||
print(f"{label:<38} CPU {100 * (c1 - c0) / (t1 - t0):5.2f}% · output pty {(b1 - b0) / (t1 - t0) / 1024:5.1f} KB/s")
|
||||
|
||||
|
||||
time.sleep(3) # warmup
|
||||
phase("FASE 1 (animasi 30fps)")
|
||||
os.write(fd, b"t") # picu toast
|
||||
time.sleep(3.5)
|
||||
os.write(fd, b"a") # reduced-motion
|
||||
time.sleep(1)
|
||||
phase("FASE 2 (reduced-motion)")
|
||||
try:
|
||||
os.kill(pid, signal.SIGKILL)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
print("selesai")
|
||||
Reference in new issue
Block a user