Skip to content
shellhacks.dev
Performance

Count process spawns in a script

Count how many processes a shell script starts with strace -f -c -e trace=execve,clone. A loop that calls date five times runs six execs, and a builtin runs one.

1 min read
Summarize in AI

A script that loops over many items is slow, and the suspicion is that it starts a new process for every item.

Shell
cat > external.sh <<'EOF'
for i in 1 2 3 4 5; do t=$(date +%s); done
EOF
cat > builtin.sh <<'EOF'
for i in 1 2 3 4 5; do printf -v t '%(%s)T' -1; done
EOF
for s in external.sh builtin.sh; do
  echo "$s:"
  strace -f -qq -c -e trace=execve,clone,clone3 bash $s 2>&1 | awk '$NF=="execve" || $NF=="clone" || $NF=="clone3" {print "  " $4, $NF}'
done
Text
external.sh:
  5 clone
  6 execve
builtin.sh:
  1 execve

strace -f follows child processes, -c prints a table of the calls instead of each one, and -e trace= limits the table to process creation, which is clone and execve on Linux. The command substitution in the first script forks a subshell for every pass and then runs date, so the five passes give five forks and six execs, counting the shell itself. The second script uses the %()T format of the printf builtin and runs a single exec. See the strace manual.

strace slows the traced program down, so use it to count calls and not to time them. It needs permission to trace, which containers and some hardened kernels deny with an error about ptrace. On macOS the equivalents are dtruss or fs_usage. %()T needs Bash 4.2 or later.

Share

More snippets

Performance

Count lines in a huge file fast

Count the lines of a big file with wc -l, which is the fastest of the usual tools. It counts newlines, so a last line without a newline is not counted.

2 min read
Performance

Find syscalls that take time

Show how long each system call takes with strace -T. The figure in angle brackets is the time spent inside the call, so a slow write or sleep stands out.

1 min read
Performance

Trace file opens of a command

Find which files a command opens with strace -e trace=openat, and add -e status=failed to see the config files it looked for and did not find.

2 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.