我们有一个用ANSI C编写的项目。通常,内存消耗不是什么大问题,但是现在我们有一个要求将程序适合256 KB RAM。我手头没有这个确切的平台,所以我在32位x86 Linux上编译我的项目(因为它提供了足够的不同工具来评估内存消耗),优化了我的功能,删除了一些功能,最终我必须拥有结论:为了能够在非常小的系统上运行(如果我们有能力的话),我们需要牺牲哪些功能。首先,我研究了Linux中的内存大小,似乎我必须优化RSS大小,而不是VSZ。但是在Linux中,即使是最小的程序也可以显示“Hello world!”。每秒一次在RSS中消耗285-320 KB:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
unsigned char cuStopCycle = 0;
void SigIntHandler(int signo)
{
printf("SIGINT received, terminating the program\n");
cuStopCycle = 1;
}
int main()
{
signal( SIGINT, SigIntHandler);
while(!cuStopCycle)
{
printf("Hello, World!\n");
sleep(1);
}
printf("Exiting...\n");
}
user@Ubuntu12-vm:~/tmp/prog_size$ size ./prog_size
text data bss dec hex filename
1456 272 12 1740 6cc ./prog_size
root@Ubuntu12-vm:/home/app# ps -C prog_size -o pid,rss,vsz,args
PID RSS VSZ COMMAND
22348 316 2120 ./prog_size
显然,该程序可以在具有64KB RAM的小型PLC上完美运行。只是linux加载了很多库。我为此程序生成了一个映射文件,所有这些数据+ bss均来自CRT库。我需要提到的是,如果我向该项目添加一些代码-10,000次“a = a + b”或操作数组2000个long int变量,我会看到代码大小,bss大小的差异,但最终该过程的RSS大小为一样,不受影响)
因此,我以此为基准,即我想要达到的点(而且我将永远无法达到这一点,因为我需要的功能不仅仅是每秒打印一条消息而已)。
这就是我的项目,在这里我删除了所有其他功能,删除了所有辅助功能,删除了除基本功能以外的所有内容。有一些方法可以进行更多优化,但并不是很多,可以删除的内容已被删除:
root@Ubuntu12-vm:/home/app/workspace/proj_sizeopt/Cmds# ls -l App
-rwxr-xr-x 1 root root 42520 Jul 13 18:33 App
root@Ubuntu12-vm:/home/app/workspace/proj_sizeopt/Cmds# size ./App
text data bss dec hex filename
37027 404 736 38167 9517 ./App
因此,我有〜36KB 的代码和〜1KB 的数据。我不在项目内部调用malloc,而是使用带有包装器库的共享内存分配,以便可以控制分配的内存量:
The total memory size allocated is 2052 bytes
显然存在malloc调用,如果用我的函数替换“malloc”调用来汇总所有分配请求,那么我看到分配了〜2.3KB 内存:
root@Ubuntu12-vm:/home/app/workspace/proj_sizeopt/Cmds# LD_PRELOAD=./override_malloc.so ./App
Malloc allocates 2464 bytes total
现在,我运行我的项目并看到消耗了600KB RAM 。
root@Ubuntu12-vm:/home/app/workspace/proj_sizeopt# ps -C App -o pid,rss,vsz,args
PID RSS VSZ COMMAND
22093 604 2340 ./App
我不明白为什么它要占用这么多内存。代码很小。没有分配太多的内存。数据量很小。为什么要占用这么多内存? 我试图分析该过程的映射:
root@Ubuntu12-vm:/home/app/workspace/proj_sizeopt# pmap -x 22093
22093: ./App
Address Kbytes RSS Dirty Mode Mapping
08048000 0 28 0 r-x-- App
08052000 0 4 4 r---- App
08053000 0 4 4 rw--- App
09e6a000 0 4 4 rw--- [ anon ]
b7553000 0 4 4 rw--- [ anon ]
b7554000 0 48 0 r-x-- libpthread-2.15.so
b756b000 0 4 4 r---- libpthread-2.15.so
b756c000 0 4 4 rw--- libpthread-2.15.so
b756d000 0 8 8 rw--- [ anon ]
b7570000 0 300 0 r-x-- libc-2.15.so
b7714000 0 8 8 r---- libc-2.15.so
b7716000 0 4 4 rw--- libc-2.15.so
b7717000 0 12 12 rw--- [ anon ]
b771a000 0 16 0 r-x-- librt-2.15.so
b7721000 0 4 4 r---- librt-2.15.so
b7722000 0 4 4 rw--- librt-2.15.so
b7731000 0 4 4 rw-s- [ shmid=0x70000c ]
b7732000 0 4 4 rw-s- [ shmid=0x6f800b ]
b7733000 0 4 4 rw-s- [ shmid=0x6f000a ]
b7734000 0 4 4 rw-s- [ shmid=0x6e8009 ]
b7735000 0 12 12 rw--- [ anon ]
b7738000 0 4 0 r-x-- [ anon ]
b7739000 0 104 0 r-x-- ld-2.15.so
b7759000 0 4 4 r---- ld-2.15.so
b775a000 0 4 4 rw--- ld-2.15.so
bfb41000 0 12 12 rw--- [ stack ]
-------- ------- ------- ------- -------
total kB 2336 - - -
并且看起来程序大小(在RSS中)仅为,只有28KB ,其余部分由共享库使用。顺便说一句,我不使用posix线程,没有显式链接到它,但是无论如何,链接器都链接了这个库,我不知道为什么(这并不重要)。如果我们更详细地查看映射:
root@Ubuntu12-vm:/home/app/workspace/proj_sizeopt# cat /proc/22093/smaps
08048000-08052000 r-xp 00000000 08:01 344838 /home/app/workspace/proj_sizeopt/Cmds/App
Size: 40 kB
Rss: 28 kB
Pss: 28 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 28 kB
Private_Dirty: 0 kB
Referenced: 28 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
...
09e6a000-09e8b000 rw-p 00000000 00:00 0 [heap]
Size: 132 kB
Rss: 4 kB
Pss: 4 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 4 kB
Referenced: 4 kB
Anonymous: 4 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
...
b7570000-b7714000 r-xp 00000000 08:01 34450 /lib/i386-linux-gnu/libc-2.15.so
Size: 1680 kB
Rss: 300 kB
Pss: 7 kB
Shared_Clean: 300 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 300 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
...
b7739000-b7759000 r-xp 00000000 08:01 33401 /lib/i386-linux-gnu/ld-2.15.so
Size: 128 kB
Rss: 104 kB
Pss: 3 kB
Shared_Clean: 104 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 104 kB
Anonymous: 0 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
...
bfb41000-bfb62000 rw-p 00000000 00:00 0 [stack]
Size: 136 kB
Rss: 12 kB
Pss: 12 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 12 kB
Referenced: 12 kB
Anonymous: 12 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
我不看PSS,因为就我而言,它没有任何意义,我只看RSS。
我可以从这张图片得出什么结论?如何准确评估应用程序的内存消耗?看一下RSS大小的过程吗?还是从所有已映射系统库的RSS大小中减去?什么是堆/堆栈大小?
对于任何建议,说明,内存消耗优化技术,具有极少量RAM的平台上的DO和DO(不要),我将不胜感激(明显的除外-将数据和代码的数量保持在最低限度)。
我还要感谢一个解释,为什么程序中的代码和数据量很少(并且不会分配太多内存),但RSS中仍然占用大量RAM。
先感谢您
最佳答案
...使我们的程序适合256 KB RAM。我手头没有这个确切的平台,所以我在32位x86 Linux上编译我的项目。
现在您将看到,Linux平台工具对您可能需要的堆栈和堆进行了合理的假设,因为它现在可以在大型计算机上运行,并且可以根据需要链接合理的库函数集。一些您不需要的,但是它“免费”为您提供。
要在目标平台上容纳256 Kb,必须为目标平台编译并使用目标平台的链接器链接到目标平台的库(和CRT)。
这些将做出不同的假设,使用可能较小的库足迹,对堆栈和堆空间进行更小的假设等。例如,为目标平台创建“Hello World”并在该目标平台上检查其需求。或使用目标平台和库的逼真的模拟器(不要忘了,操作系统在某种程度上决定了库必须做什么)。
而且如果它仍然太大,则必须重写或调整整个CRT和所有库...。
关于c - 应用程序内存优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31389894/