Skip to content

elfuse real-workload syscall frequency ranking (Top 50) #224

Description

@Max042004

Environment: origin/main (435a546) + PR #191 (OCI tooling, 9 commits) + instrumentation
commit 3312482 + unpack setuid-EPERM fallback fix (not separately committed).

Methodology

  • Added an ELFUSE_SYSCALL_STATS_DIR whole-lifetime stats mode (built on the
    existing src/debug/syscall-hist.c): recording does not freeze at the first
    execve, fork children (fresh posix_spawn images) record independently, and
    each guest process writes <host-pid>.stats (name count total_ns) at exit
    (atexit / elfuse_launch). Summing the per-process files yields exact
    process-tree totals.
  • The watchdog was raised to --timeout 3600 via an ELFUSE_BIN wrapper so
    long compile bursts are not killed (the 10 s default per-iteration alarm;
    note --timeout 0 is not "no timeout" — 0 selects worker-thread semantics).

Workloads (five categories, 116 guest processes)

workload image content syscalls processes
jvm eclipse-temurin:21 javac compile of a multi-class program + java run (collections, file I/O, SHA-256, 8 threads, subprocess) 3,028,653 8
python python:3.12-slim JSON/regex churn, sqlite3 (20k inserts + queries), 400 small-file I/O, os.walk over the stdlib, 10 subprocesses, 4 threads 1,364,400 11
go golang:1.23-alpine go version + gofmt over stdlib trees (net/runtime/crypto) + gofmt -d fmt 46,037 6
node node:22-alpine module loading, fs/crypto/zlib/JSON, then an HTTP server taking 302 host-side curl requests before /quit 18,740 1
c-compile gcc:14 30-file C project via make -j1 + sqlite amalgamation (8 MB TU) gcc -O1 compile+link + a sqlite3 query 82,606 90

Total: 4,540,436 syscalls, 89 distinct.

Top 50 ranking (five workloads combined, descending)

# syscall count share% cum% jvm python go node c-compile
1 futex 2,559,392 56.369 56.37 1,517,216 1,040,892 166 1,118 0
2 clock_gettime 1,849,178 40.727 97.10 1,507,075 308,525 30,326 3,251 1
3 readlinkat 48,107 1.060 98.16 109 3 1 15 47,979
4 openat 12,457 0.274 98.43 240 1,213 1,572 633 8,799
5 read 9,449 0.208 98.64 409 972 2,903 1,230 3,935
6 close 6,978 0.154 98.79 209 1,255 1,573 936 3,005
7 mmap 6,152 0.135 98.93 662 181 87 2,477 2,745
8 fcntl 5,737 0.126 99.05 31 2,035 2,926 628 117
9 newfstatat 5,347 0.118 99.17 106 1,582 1,488 0 2,171
10 fstat 5,330 0.117 99.29 171 2,131 2 14 3,012
11 lseek 3,785 0.083 99.37 104 1,712 0 11 1,958
12 munmap 3,532 0.078 99.45 195 99 2 2,406 830
13 epoll_ctl 3,515 0.077 99.53 0 0 2,903 612 0
14 write 3,011 0.066 99.59 260 454 4 305 1,988
15 mremap 2,050 0.045 99.64 0 4 0 2,046 0
16 brk 2,004 0.044 99.68 27 81 6 9 1,881
17 rt_sigaction 1,928 0.042 99.73 170 767 353 35 603
18 epoll_pwait 1,769 0.039 99.76 0 0 260 1,509 0
19 mprotect 1,234 0.027 99.79 219 98 6 79 832
20 rt_sigprocmask 1,155 0.025 99.82 353 69 64 63 606
21 ioctl 980 0.022 99.84 20 869 2 5 84
22 pread64 912 0.020 99.86 405 507 0 0 0
23 getdents64 724 0.016 99.87 10 426 234 0 54
24 faccessat 709 0.016 99.89 36 11 0 0 662
25 madvise 624 0.014 99.90 70 4 485 64 1
26 nanosleep 573 0.013 99.92 0 0 573 0 0
27 prlimit64 367 0.008 99.92 26 11 3 6 321
28 setsockopt 305 0.007 99.93 2 0 0 303 0
29 writev 304 0.007 99.94 0 0 2 302 0
30 accept4 302 0.007 99.94 0 0 0 302 0
31 shutdown 302 0.007 99.95 0 0 0 302 0
32 execve 196 0.004 99.96 8 10 5 0 173
33 pwrite64 192 0.004 99.96 0 192 0 0 0
34 getcwd 163 0.004 99.96 6 57 1 1 98
35 set_robust_list 163 0.004 99.97 55 15 0 0 93
36 rseq 154 0.003 99.97 49 15 0 0 90
37 clone3 131 0.003 99.97 41 4 0 0 86
38 sched_getaffinity 124 0.003 99.98 121 0 3 0 0
39 set_tid_address 120 0.003 99.98 9 11 8 2 90
40 exit_group 116 0.003 99.98 8 11 6 1 90
41 wait4 116 0.003 99.98 7 10 10 0 89
42 sysinfo 90 0.002 99.99 3 0 0 0 87
43 prctl 43 0.001 99.99 42 0 0 1 0
44 renameat 42 0.001 99.99 0 42 0 0 0
45 pipe2 41 0.001 99.99 7 30 0 4 0
46 unlinkat 41 0.001 99.99 3 4 0 0 34
47 clone 39 0.001 99.99 6 10 14 6 3
48 dup3 37 0.001 99.99 9 20 8 0 0
49 gettimeofday 34 0.001 99.99 4 0 0 0 30
50 statx 34 0.001 99.99 33 0 0 1 0

Beyond the top 50: 39 syscalls, 348 calls (0.008%).

Key takeaways

  1. futex (56.4%) + clock_gettime (40.7%) = 97.1%. Thread-heavy runtimes
    (JVM, CPython) are completely dominated by these two.
  2. A futex fast-path is the second target: mostly uncontended wake/wait;
    1.51 M calls from the JVM, 1.04 M from CPython.
  3. readlinkat at Tighten madvise Linux parity for hole/anon/shared #3 comes almost entirely from gcc (47,979 of 48,107):
    the gcc driver re-resolves its own and its tools' paths for every TU — a
    signature of compile workloads.
  4. The file-I/O family (openat/read/close/fstat/newfstatat/lseek/write)
    sums to about 1%, but it is the part that hits the host FS on every call,
    with a much higher per-call cost than futex.
  5. Shares correlate strongly with workload mix (jvm+python are 97% of total
    volume); the per-workload columns are more meaningful than the combined
    share. Node's signature is epoll/accept4/writev/mremap, go (gofmt) is
    fcntl/epoll_ctl/read, compiles are readlinkat/openat/brk.

Ranks 51–89 (the full tail)

# syscall count jvm python go node c-compile
51 sigaltstack 33 9 0 24 0 0
52 getrusage 29 0 0 0 0 29
53 ppoll 23 3 20 0 0 0
54 exit 22 13 4 0 5 0
55 readv 22 0 0 0 22 0
56 socket 21 14 2 0 1 4
57 close_range 20 0 20 0 0 0
58 capget 18 0 0 0 18 0
59 connect 14 8 2 0 0 4
60 dup 13 1 0 0 0 12
61 fchdir 12 12 0 0 0 0
62 fdatasync 12 0 12 0 0 0
63 sched_yield 10 6 0 4 0 0
64 uname 10 4 0 2 3 1
65 statfs 9 9 0 0 0 0
66 epoll_create1 7 0 1 3 3 0
67 rt_sigreturn 7 5 0 2 0 0
68 eventfd2 6 0 0 3 3 0
69 ftruncate 6 6 0 0 0 0
70 mkdirat 6 4 1 0 1 0
71 umask 6 4 0 0 0 2
72 getrandom 5 0 3 0 0 2
73 chdir 4 1 0 0 0 3
74 clock_getres 4 3 0 0 1 0
75 faccessat2 4 3 0 1 0 0
76 io_uring_setup (425) 3 0 0 0 3 0
77 clock_nanosleep 3 3 0 0 0 0
78 fchown 3 0 3 0 0 0
79 flock 3 3 0 0 0 0
80 getpeername 2 1 0 0 0 1
81 splice 2 2 0 0 0 0
82 tgkill 2 0 0 2 0 0
83 bind 1 0 0 0 1 0
84 fchmodat 1 0 0 0 0 1
85 getresgid 1 1 0 0 0 0
86 getresuid 1 1 0 0 0 0
87 listen 1 0 0 0 1 0
88 llistxattr 1 1 0 0 0 0
89 membarrier 1 0 0 0 1 0

Ranks 51+ total 348 calls (0.008%) — almost entirely one-shot startup calls
(capget, getresuid, membarrier) or workload signatures (node's socket family,
python's fdatasync/close_range).

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions