// fpsample — phys_footprint of the newest com.apple.WebKit.WebContent process
// every <ms> milliseconds (the number WebKit's memory-kill check reads).
//   fpsample <ms> <parent-pid> > out.tsv      (exits when the parent exits)
import Darwin
import Foundation
let ms = UInt32(CommandLine.arguments.count > 1 ? Int(CommandLine.arguments[1]) ?? 20 : 20)
let parent = pid_t(CommandLine.arguments.count > 2 ? Int32(CommandLine.arguments[2]) ?? 0 : 0)
func webContentPid() -> pid_t {
    var pids = [pid_t](repeating: 0, count: 4096)
    let n = proc_listallpids(&pids, Int32(pids.count * MemoryLayout<pid_t>.size))
    var best: pid_t = 0
    var buf = [CChar](repeating: 0, count: 4096)
    for p in pids.prefix(Int(n)) where p > best {
        if proc_pidpath(p, &buf, UInt32(buf.count)) > 0, String(cString: buf).hasSuffix("com.apple.WebKit.WebContent") { best = p }
    }
    return best
}
print("t_ms\tpid\tfootprint_mb"); fflush(stdout)
var pid = webContentPid(); var last = Date()
while parent == 0 || kill(parent, 0) == 0 {
    if Date().timeIntervalSince(last) > 1 || pid == 0 { pid = webContentPid(); last = Date() }
    if pid > 0 {
        var info = rusage_info_v4()
        let r = withUnsafeMutablePointer(to: &info) { $0.withMemoryRebound(to: rusage_info_t?.self, capacity: 1) { proc_pid_rusage(pid, RUSAGE_INFO_V4, $0) } }
        if r == 0 { print("\(Int(Date().timeIntervalSince1970 * 1000))\t\(pid)\t\(info.ri_phys_footprint >> 20)"); fflush(stdout) }
    }
    usleep(ms * 1000)
}
