elfuse real-workload syscall frequency ranking (Top 50)
@Max042004 is already working on this.
Since Sep 7, 2026.
Assessment
This issue has not been assessed yet.
Description
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_DIRwhole-lifetime stats mode (built on the
existingsrc/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 3600via anELFUSE_BINwrapper so
long compile bursts are not killed (the 10 s default per-iteration alarm;
note--timeout 0is 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
- futex (56.4%) + clock_gettime (40.7%) = 97.1%. Thread-heavy runtimes
(JVM, CPython) are completely dominated by these two. - A futex fast-path is the second target: mostly uncontended wake/wait;
1.51 M calls from the JVM, 1.04 M from CPython. - readlinkat at #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. - 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. - 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).
- Dominant language
- C
- Stars
- 268
- Forks
- 26
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 48
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from sysprog21/elfuse
-
Difficulty 3/5 1-2 days Newbie friendliness 76/100
-
Difficulty 5/5 Over a week Newbie friendliness 45/100
-
`rt_sigreturn` overwrites the restored X8, so a signal taken on an `svc` re-enters it as syscall 2 Open
Difficulty 4/5 3-5 days Newbie friendliness 64/100
All issues in sysprog21/elfuse
Similar issues
-
level/task module/gcp type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
-
Difficulty 1/5 Under an hour Newbie friendliness 86/100
hapostgres/pg_auto_failover#1190 ·
-
docs
Difficulty 1/5 Under an hour Newbie friendliness 85/100
-
P3 sonic-vpp
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
sonic-net/sonic-buildimage#29662 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 94/100
spack/spack-packages#6586 ·