15

我有一个用 C++ 编写的服务器应用程序。启动后,它在 x86 Linux(Ubuntu 8.04,GCC 4.2.4)上使用了大约 480 KB 的内存。我认为 480 KB 是过多的内存:服务器甚至还没有做任何事情,没有客户端连接到服务器。(另请参阅下面的评论,我在其中解释了为什么我认为 480 KB 是很多内存。)服务器在初始化期间所做的唯一事情是产生一两个线程,设置一些套接字以及其他简单的事情t 非常占用内存。

请注意,我说的是实际内存使用情况,而不是 VM 大小。我通过在一台闲置的笔记本电脑上启动 100 个服务器实例并在启动服务器实例之前和之后使用“空闲”测量系统内存使用情况来测量它。我已经考虑了文件系统缓存和类似的东西。

经过一些测试后,即使服务器本身没有做任何事情,C++ 运行时中的某些东西也会导致我的服务器使用这么多内存。例如,如果我插入

getchar(); return 0;

紧接着

int main(int argc, char *argv[]) {

那么每个实例的内存使用量仍然是 410 KB!

我的应用程序仅依赖于 Curl 和 Boost。我有相当多的 C 编程经验,而且我知道 C 库在我使用它们之前不会增加内存消耗。

我发现的其他内容:

  • 一个简单的 hello world C 应用程序消耗大约 50 KB 的内存。
  • 一个简单的 hello world C 应用程序链接到 Curl,但不使用 Curl,也消耗大约 50 KB 的内存。
  • 一个简单的 hello world C++ 应用程序(没有 Boost)消耗大约 100 KB 的内存。
  • 一个简单的 hello world C++ 应用程序包含一些 Boost 标头,但实际上并不使用 Boost,它会消耗大约 100 KB 的内存。使用“nm”检查可执行文件时没有 Boost 符号。

因此,我的结论如下:

  1. Gcc 会丢弃未使用的 Boost 符号。
  2. 如果我的应用程序使用 Boost,那么 C++ 运行时中的某些东西(可能是动态链接器)会导致它使用大量内存。但是什么?我如何找出这些东西是什么,我能做些什么呢?

我记得几年前关于 C++ 动态链接器问题的一些 KDE 讨论。当时的 Linux C++ 动态链接器导致 KDE C++ 应用程序的启动时间变慢和大量内存消耗。据我所知,这些问题已在 C++ 运行时中得到修复。但是类似的事情可能是我看到的过度内存消耗的原因吗?

非常感谢 gcc/动态链接专家的回答。

对于那些好奇的人,有问题的服务器是 Phusion Passenger 的日志代理:https ://github.com/FooBarWidget/passenger/blob/master/ext/common/LoggingAgent/Main.cpp

4

3 回答 3

5

C 运行时分配的内存比您的进程在正常操作中实际使用的内存要多。这是因为在内核级别分配内存非常慢,并且只能在页面大小的块中完成(页面大小在 x86 机器上通常为 4kb,但它可以更大,在 x64 机器上通常为 8kb 或更多)。

此外,当 C 运行时收到一个它无法满足的分配请求时,它通常会分配超出必要的分配空间,以消除大部分时间访问内核的开销。

最后,如果您使用的是 boost goodies,它们可能依赖于一些 STL 组件,例如std::vector. 这些组件使用 为元素分配空间std::allocator<T>,在某些情况下会再次分配比实际使用更多的空间。(特别是,基于节点的结构,如std::map,std::setstd::list通常这样做是为了将列表或树的节点放在同一个内存页面上)

长话短说:不要担心这个。半兆内存在任何想象中都不算多(至少现在是这样),其中大部分可能只是摊销动态分配函数的使用。写下你的实际服务器,如果它使用太多内存,那么看看减少内存使用的方法。

编辑:如果您使用的 boost 组件恰好是 asio,并且您正在使用套接字,那么您还应该知道为了维护套接字的缓冲区而消耗了一些内存。

于 2010-11-14T18:10:34.417 回答
1

减少内存消耗的一种方法是减少线程堆栈大小。

关于boost,正如Steve Jessop评论的那样,你必须比“boost”更具体一点。

于 2010-11-14T18:01:38.187 回答
1

听起来您的某些动态加载库存在基地址冲突问题。如果它们在加载期间需要重新定位,它们将被映射为私有固定副本。

prelink在整个系统中重新运行。如果库在其首选地址加载,它将被映射为共享内存,并且无论有多少进程正在使用它,都只需要一份代码副本。

顺便说一句,prelink这也是 KDE 的修复程序。

于 2010-11-14T18:25:01.897 回答