hack/podmansnoop

Add a script to measure the execution times of podman, crun, run and
conmon.  It's a trimmed down version of the exitsnoop tool and intended
to guide us in future performance optimizations.

The below output was generated when running

`podman run --net=host docker.io/library/alpine:latest true`

```
podman (snoop) $ sudo ./hack/podmansnoop
PCOMM            PID     PPID    TID     AGE(ms)
conmon           51580   51569   51580   1.67
conmon           51583   51569   51583   3.53
crun             51591   51590   51591   18.28
crun             51593   51569   51593   2.48
conmon           51606   51594   51606   0.85
crun             51608   51594   51608   2.50
podman           51594   51590   51594   176.27
conmon           51590   1950    51590   214.78
podman           51569   40964   51569   431.36
```

In the future, it would be helpful to add the arguments of the commands.
`execsnoop` can reveal them quite nicely but I did not manage to merge
the two scripts due to time constraints.

Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2022-10-28 15:12:11 +02:00
parent 26e5661c27
commit 3ad5827b2d

98
hack/podmansnoop Executable file
View File

@ -0,0 +1,98 @@
#!/usr/bin/env python
from __future__ import print_function
# Based on the `exitsnoop` scripts at https://github.com/iovisor/bcc/blob/master/tools/exitsnoop.py
import argparse
import os
import platform
import re
import signal
import sys
from bcc import BPF
from datetime import datetime
from time import strftime
bpf_src = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
#define ARGSIZE 128
struct data_t {
u64 start_time;
u64 exit_time;
u32 pid;
u32 tid;
u32 ppid;
u32 sig_info;
char task[TASK_COMM_LEN];
char argv[ARGSIZE];
};
BPF_PERF_OUTPUT(events);
TRACEPOINT_PROBE(sched, sched_process_exit)
{
struct task_struct *task = (typeof(task))bpf_get_current_task();
if (task->pid != task->tgid) { return 0; }
struct data_t data = {};
data.start_time = task->start_time,
data.exit_time = bpf_ktime_get_ns(),
data.pid = task->tgid,
data.tid = task->pid,
data.ppid = task->real_parent->tgid,
data.sig_info = task->exit_code & 0xFF,
bpf_get_current_comm(&data.task, sizeof(data.task));
events.perf_submit(args, &data, sizeof(data));
return 0;
}
"""
def _print_header():
print("%-16s %-7s %-7s %-7s %-7s" %
("PCOMM", "PID", "PPID", "TID", "AGE(ms)"))
buffer = None
def _print_event(cpu, data, size): # callback
"""Print the exit event."""
global buffer
e = buffer["events"].event(data)
task = e.task.decode()
if task == "3":
# For absolutely unknown reasons, 'crun' appears as '3'.
task = "crun"
if task not in ["podman", "crun", "runc", "conmon", "netavark", "aardvark-dns"]:
return
age = (e.exit_time - e.start_time) / 1e6
print("%-16s %-7d %-7d %-7d %-7.2f " %
(task, e.pid, e.ppid, e.tid, age), end="")
print()
def snoop(bpf, event_handler):
bpf["events"].open_perf_buffer(event_handler)
while True:
bpf.perf_buffer_poll()
def main():
global buffer
try:
buffer = BPF(text=bpf_src)
_print_header()
snoop(buffer, _print_event)
except KeyboardInterrupt:
print()
sys.exit()
return 0
if __name__ == '__main__':
main()