首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何减少默认的C++内存消耗?

问如何减少默认的C++内存消耗?
EN

Stack Overflow用户
提问于 2010-11-14 16:53:28
回答 3查看 4.3K关注 0票数 16

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

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

经过一些测试后,似乎C++运行时中的某些内容导致我的服务器使用了这么多内存,即使服务器本身什么也不做。例如,如果我插入

代码语言:javascript
复制
getchar(); return 0;

就在

代码语言:javascript
复制
int main(int argc, char *argv[]) {

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

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

我发现的其他东西:

  • 一个简单的hello world C应用程序消耗了大约50 KB的内存。
  • --一个简单的hello world C应用程序链接到Curl,但如果不使用Curl,也会消耗大约50 KB的内存。
  • --简单的hello world C++应用程序(没有助推)会消耗大约100 KB的内存。
  • 是一个简单的hello world C++应用程序,它包含一些助推头,但实际上不使用Boost,消耗了大约100 KB的内存。当检查带有‘nm’的可执行文件时没有提升符号。

因此,我的结论如下:

  1. Gcc扔掉了未使用的Boost符号。
  2. 如果我的应用程序使用Boost,那么C++运行时中的某个东西(可能是动态链接器)会导致它使用大量内存。,但是怎么办?我怎样才能弄清楚这些东西是什么,我能做些什么呢?

我记得几年前关于C++动态链接器问题的一些KDE讨论。当时的Linux C++动态链接器导致KDE C++应用程序的启动时间慢,内存消耗大。据我所知,这些问题已经在C++运行时中解决了。但是,类似的东西会不会是我所看到的记忆过度消耗的原因呢?

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

对于那些好奇的人来说,所讨论的服务器是Phusion乘客的日志代理:https://github.com/FooBarWidget/passenger/blob/master/ext/common/LoggingAgent/Main.cpp

EN

回答 3

Stack Overflow用户

发布于 2010-11-14 18:10:34

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

此外,当C运行时接收到它无法满足的分配请求时,它通常会分配超出大多数时间进入内核的开销所必需的资源。

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

长话短说:别担心这个。半个meg的内存并不是任何想象中的东西(至少现在是这样),而且其中大部分可能只是在分摊动态分配函数的使用。编写您的实际服务器,如果它使用过多的内存,那么请考虑减少内存使用的方法。

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

票数 6
EN

Stack Overflow用户

发布于 2010-11-14 18:01:38

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

关于boost,正如Steve所说,你必须比"boost“更具体一些。

票数 2
EN

Stack Overflow用户

发布于 2010-11-14 18:25:01

听起来,您在一些动态加载库上出现了基址冲突问题。如果它们在加载过程中需要重新定位,它们将被映射为私有的固定副本。

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

顺便说一句,prelink也是KDE的修复方法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4178530

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档