gpt4 book ai didi

c - 应用程序内存优化

转载 作者:行者123 更新时间:2023-12-02 04:47:54 24 4
gpt4 key购买 nike

我们有一个用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
  • 因此,我看到我的项目的RSS大小为 40KB ,但仅使用 28 KB 。这是否意味着该项目将适合 256 KB RAM
  • 的大小为 132KB ,但仅使用 4 KB 。这是为什么?我确信在小型嵌入式平台上会有所不同。
  • 堆栈 136KB ,但仅使用 12KB
  • GLIBC / LD显然会消耗一些内存,但是在嵌入式平台上它将确切存储什么?

  • 我不看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/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com