c - 应用程序内存优化

标签 c memory memory-management rss

我们有一个用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/

    相关文章:

    c - (unsigned char *)&variable_name 是什么意思?

    c - 使用 malloc 时出现 "Invalid conversion"错误?

    linux - 主引导记录,分区表

    c - C中位图文件的像素操作

    linux - 为什么我们需要 x86 上的 zone_highmem?

    c - 在 xtaskcreate 中设置完美的 usStackDepth 重要吗?

    c - 我不明白这个程序出了什么问题

    Java 销毁变量

    iphone - iOS模拟内存警告问题

    objective-c - C和Objective-C中返回地址的内存分配