I just started studying about system calls. I would like to know what causes overhead when a system call is made.
For example, if we consider getpid(), when a system call is made to getpid() my guess is that if the control is currently in the child process then a context switching has to be made to enter the parent process to get the pid. Can that contribute to overhead?
Also when getpid() is called, there will be some metadata transfer across the user-space boundary and enters and exits the kernel.So will the constant switching between user space and kernel also cause some overhead?
I've done some more precise benchmarking at an x86-64 Linux (compiled with -O3):
ns relative(rounded) function
4.89 1 regular_function //just a value return
6.05 1 getpid //glibc caches this one (forks invalidate the cached value)
17.7 4 sysconf(_SC_PAGESIZE)
22.6 5 getauxval(AT_EUID)
25.4 5 sysconf(_SC_NPROCESSORS_ONLN)
27.1 6 getauxval(AT_UID)
54.1 11 gettimeofday
235 48 geteuid
261 53 getuid
264 54 getppid
314 64 sysconf(_SC_OPEN_MAX)
622 127 pread@0 // IO funcs benchmarked with 1 bytes quantities
638 130 read // through a 1 Gigabyte file
1690 346 write
1710 350 pwrite@0
The cheapest "syscalls" are the ones that go through the auxiliary vector (~20–30ns). The calls in the middle (~250–310ns) should reflect the average overhead most accurately as there shouldn't be much work to be done in the kernel with them.
For comparison, malloc+free pairs with small size requests (<64 bytes => no system calls) cost about 70-80ns (see my answer at Cost of static memory allocation vs dynamic memory allocation in C).
https://softwareengineering.stackexchange.com/questions/311165/why-isnt-there-generic-batching-syscall-in-linux-bsd/350173 has some interesting ideas about how the syscall overhead could be minimized.