我是开发人员团队的一员,他们编写了一套相当复杂的基于C ++的守护进程,其中十几个实例同时在基于x86的Xenomai /实时Linux服务器上运行。
守护进程全部编译成一个可执行文件(BusyBox样式),其main()函数检查argv [1]并(基于其值)调用适当的守护进程的subdaemonname_main()函数。 / p>
前几天我注意到(通过在Linux服务器上执行" ps -ww -eio pid,%mem,rss,args")每个进程占用大约35兆字节的RAM服务器,即使进程只是在main()的最顶层睡觉。为了比较,如果我编译"你好世界" (作为一个单独的可执行文件),ps表明它的进程几乎不占用RAM。
我从中得到的教训是:将一些C ++程序编译成单个可执行文件的缺点是,可执行文件运行的每个进程都将设置在所有.cpp中声明的所有静态/全局对象文件,甚至是进程将运行的特定子守护进程永远不会使用的文件。这是浪费RAM,我能够在代码中找到几个大的静态C ++对象,并将它们更改为非静态以减少RAM使用。
我的问题是,是否有任何(半)自动方式可以让我获得构成35MB / before-main()内存使用过程的清单?我可以通过手动浏览每个.cpp文件来寻找静态或全局对象声明来做到这一点,但由于它是一个需要很长时间的大代码库,我可能仍然会遗漏一些东西。有没有一种快速的方法来分析流程的静态对象内存表?拥有这些信息可以让我更好地了解进一步降低RAM使用率的最佳机会。
答案 0 :(得分:2)
看一下链接图(ld --print-map,或者gcc -Wl, - 如果你要用gcc链接打印地图),它应该给你一些想法。哪些静态对象进入最终的可执行文件。
如果他们被宣布的那样,你肯定会把他们全部放在.data中。链接器无法告诉某些数据永远不会被使用,所以它必须映射所有数据。
在合理可读的C ++中避免这种情况的唯一简单方法可能是放置"静态"在堆栈中,特别是它们各自的主_ *()函数的堆栈,以及传递指针。这是假设"静态"大部分都是空的。任何实际的静态数据仍然在.data中,并且没有办法避免它。
使用一些黑色ELF魔法,可能有专门的.data部分并按需映射它们,但我强烈怀疑它不值得努力。尤其是C ++及其怪癖。