Reputation: 31
I am studying static linking and dynamic linking, and my understanding is that static linking consumes more memory and disk space compared to dynamic linking. It is evident that static linking occupies more disk space because the static libraries are compiled into each executable file. But how can I verify that static linking consumes more memory space? For this purpose, I have designed a small experiment as described below.
Step 1: Create a C file named "mylib.c"
//mylib.c
#include <unistd.h>
// This function is designed to create a massive .text section.
void many_code() {
asm volatile (
"movabs $0x1122334455667788, %%rax \n\t"
"movabs $0x1122334455667788, %%rax \n\t"
"movabs $0x1122334455667788, %%rax \n\t" <----- This line is repeated one million times.
...
::: "rax"
);
sleep(-1);
}
Step 2: Execute "gcc -c mylib.c -o mylib.o" to compile the source file into an object file.
Step 3: Create a static library by using the command "ar -r libmy.a mylib.o".
Step 4: Create a second C file named "use_st_lib.c".
// use_st_lib.c
extern void many_code();
int main() {
many_code();
return 0;
}
Step 5: Create an executable file "use_st_lib_0.out" by using static linking with the command "gcc use_st_lib.c -static libmy.a -o use_st_lib_0".
Step 6: Create a second executable file by using static linking with the command "gcc use_st_lib.c -static libmy.a -o use_st_lib_1".
➜ static git:(master) ✗ ls -hl
total 91M
-rw-r--r-- 1 root root 9.6M May 29 09:37 libmy.a
-rw-r--r-- 1 root root 51M May 27 23:33 mylib.c
-rw-r--r-- 1 root root 9.6M May 29 09:37 mylib.o
-rwxr-xr-x 1 root root 11M May 29 10:11 use_st_lib_0
-rwxr-xr-x 1 root root 11M May 29 10:12 use_st_lib_1
-rw-r--r-- 1 root root 76 May 27 22:10 use_st_lib.c
Step 7: In another terminal session, use the "top" command and set the refresh time to 1.0s. Apply a filter condition with COMMAND=use_st_lib.
top - 10:21:59 up 15 days, 17:40, 4 users, load average: 0.00, 0.01, 0.05
Tasks: 79 total, 1 running, 78 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.0 us, 1.0 sy, 0.0 ni, 98.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1756.5 total, 793.8 free, 133.2 used, 829.5 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1469.8 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
Step 8: Run the process "use_st_lib_0" in the background by using the command "./use_st_lib_0 &".
➜ static git:(master) ✗ ./use_st_lib_0 &
[1] 31239
top - 10:31:06 up 15 days, 17:49, 4 users, load average: 0.07, 0.06, 0.06
Tasks: 80 total, 1 running, 79 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1756.5 total, 793.6 free, 133.1 used, 829.8 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1469.9 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31239 root 25 5 10.6m 9.5m 9.5m S 0.0 0.5 0:00.00 use_st_lib_0
Step 9: Run the process "use_st_lib_1" in the background by using the command "./use_st_lib_1 &".
➜ static git:(master) ✗ ./use_st_lib_1 &
[2] 31309
top - 10:32:02 up 15 days, 17:50, 4 users, load average: 0.03, 0.05, 0.05
Tasks: 81 total, 1 running, 80 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 1.0 sy, 0.0 ni, 99.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1756.5 total, 793.3 free, 133.4 used, 829.9 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1469.6 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31309 root 25 5 10.6m 9.5m 9.5m S 0.0 0.5 0:00.00 use_st_lib_1
31239 root 25 5 10.6m 9.5m 9.5m S 0.0 0.5 0:00.00 use_st_lib_0
Here are my questions:
1、Why does my program show SHR (Shared Memory) usage in the output of the top command? (I expected this column to be 0.)
2、After starting use_st_lib_0, the RES (Resident Memory) shows a usage of 9.5m, but the memory usage displayed at the top of the top command does not increase. (I expected it to change from 133.2 used to 123.7 used.)
3、Similarly, after starting use_st_lib_1, the output of the top command shows little or no change. (I expected it to change from 123.7 used to 114.2 used.)
4、In the above steps, where did I make mistakes, or what kind of deviation might have occurred in my understanding?
Above are the attempts I made and the results I expected.
Upvotes: 0
Views: 222
Reputation: 213877
my understanding is that static linking consumes more memory and disk space compared to dynamic linking.
That understanding is grossly incomplete.
If you have a single ./a.out
binary, that binary would generally consume less memory and less disk space when fully statically linked.
This is because:
PLT
and GOT
), nor for dynamic relocations. These can consume a lot of space.OTOH, if you have multiple binaries which all use the same shared library, and you run all these binaries at the same time, then the total memory and disk space used by them would generally be smaller with dynamic linking, than if each binary was fully statically linked.
That is because you don't need to make a copy of the library as part of each executable, and you don't need to load the code for that library into memory more that once.
Another complication is that Linux uses demand paging, which means that your executable will not consume much RAM unless it actually runs all the code in it, accesses the data, etc.
P.S.
Using top
is generally not a good way to account for memory of the process. Its output could be very misleading. You should read man top
carefully.
On Linux you can actually account for every page of physical memory by looking in /proc/$pid/pagemap
(if your kernel is configured with CONFIG_PROC_PAGE_MONITOR
).
Upvotes: 2