网络服务器中的内存管理

11 views
Skip to first unread message

gamemake

unread,
Jul 25, 2008, 3:54:10 AM7/25/08
to 高性能网络编程邮件列表
我做的服务器程序是用C开发的,关于内存方面我是这么做的:
1. 所有内存块都是固定大小
2. 分配和释放由mempool管理
这么做了之后程序稳定运行之后基本就没有内存分配了。

我以前在windows下做过一个试验过echo server,连接全部为短连接。
静态分配内存和动态分配内存相差的很多,静态分配内存基本不用 user cpu。动态分配user cpu是 kernel的4倍。

不知道大家是怎么解决这个问题的?

jinbiao xu

unread,
Jul 25, 2008, 4:07:42 AM7/25/08
to dev4s...@googlegroups.com
我有个朋友 他们服务器 没有用内存出池很糟糕。
基本做服务器长期运行的都要使用 内存池 直接管理内存 。

 
在08-7-25,gamemake <game...@gmail.com> 写道:

christanxw

unread,
Jul 25, 2008, 4:11:03 AM7/25/08
to 高性能网络编程邮件列表
服务器上多线程架构吗?如果是,内存池又是如何做到既高效又线程安全的?


On 7月25日, 下午4时07分, "jinbiao xu" <xjb...@gmail.com> wrote:
> 我有个朋友 他们服务器 没有用内存出池很糟糕。
> 基本做服务器长期运行的都要使用 内存池 直接管理内存 。
>
> 在08-7-25,gamemake <gamem...@gmail.com> 写道:
>
>
>
> > 我做的服务器程序是用C开发的,关于内存方面我是这么做的:
> > 1. 所有内存块都是固定大小
> > 2. 分配和释放由mempool管理
> > 这么做了之后程序稳定运行之后基本就没有内存分配了。
>
> > 我以前在windows下做过一个试验过echo server,连接全部为短连接。
> > 静态分配内存和动态分配内存相差的很多,静态分配内存基本不用 user cpu。动态分配user cpu是 kernel的4倍。
>
> > 不知道大家是怎么解决这个问题的?
>
> --
> 艰苦奋斗,勇敢前进!

esx

unread,
Jul 25, 2008, 4:19:04 AM7/25/08
to 高性能网络编程邮件列表
其实在很多情况下,如果设计得当,非线程安全的内存池就可以解决问题了。
另外,很多时候,线程安全的线程池,即使是使用无锁数据结构,其效率也不一定比系统提供的malloc高多少。
当然,这还和系统的malloc的实现有关。Linux的内存管理就不太敢恭维。
> > 艰苦奋斗,勇敢前进!- Hide quoted text -
>
> - Show quoted text -

christanxw

unread,
Jul 25, 2008, 4:24:25 AM7/25/08
to 高性能网络编程邮件列表
内存池不只是为提高内存分配速度,同时可以减少内存碎片,这对系统性能也是很有作用的。
也想在项目中加入内存池,但还没想到有什么好方法来做线程安全。加锁,但又怕锁会成为瓶颈。
我自己也倾向于每个线程单独一个内存池,每个线程内的对象分配互不干扰。
> > - Show quoted text -- 隐藏被引用文字 -
>
> - 显示引用的文字 -

gamemake

unread,
Jul 25, 2008, 10:25:49 AM7/25/08
to 高性能网络编程邮件列表
每个线程都有自己的内存池,对模式上的限制太多. 线程之间难免需要传递数据.
以我的经验, 固定大小的内存池就可以满足需求(不同大小的内存用不同大小的内存池)。
要做到上面说的,逻辑数据尽量用数组。

yayanyang

unread,
Jul 28, 2008, 10:25:23 PM7/28/08
to 高性能网络编程邮件列表
在线程之间进行数据传递,可以通过拷贝的方式。不过对于服务端程序来说。太多的线程间交互本身应该就是设计不佳的表现。
> > > - 显示引用的文字 -- 隐藏被引用文字 -
>
> - 显示引用的文字 -

sunway

unread,
Jul 29, 2008, 2:46:16 AM7/29/08
to 高性能网络编程邮件列表
我的做法是,
系统内分2类内存池。
1,线程安全内存池。
2,线程不安全内存池。

1.每线程有自己的线程不安全内存池,本线程内逻辑使用。

2.线程间数据
若小块内存通过 COPY内存 的队列方式传递。
大块内存使用线程安全的内存池。

基本可以满足大部分需求。



On 7月25日, 下午10时25分, gamemake <gamem...@gmail.com> wrote:
> > > - 显示引用的文字 -- 隐藏被引用文字 -
>
> - 显示引用的文字 -

yul...@gmail.com

unread,
Jul 29, 2008, 3:12:29 AM7/29/08
to 高性能网络编程邮件列表
不知道你说的线程安全是不是还是加锁实现的,还是有其他方案。
如果是加锁的话,线程安全和不安全的区别反倒可以模糊,不跨线程的使用自然是安全的,跨线程使用时加锁。使用同一内存池也就可以了,还避免了copy。
除非当我跨线程使用线程不安全数据时你可以自动帮我处理到线程安全池。

--------------------------------------------------
From: "sunway" <sunh...@gmail.com>
Sent: Tuesday, July 29, 2008 2:46 PM
To: "高性能网络编程邮件列表" <dev4s...@googlegroups.com>
Subject: Re: 网络服务器中的内存管理

关中刀客

unread,
Jul 29, 2008, 4:22:31 AM7/29/08
to 高性能网络编程邮件列表
该加锁的时候还是需要加锁吧,这点貌似没办法了,用那个lockfree就不知道了

On 7月29日, 下午3时12分, <yule...@gmail.com> wrote:
> 不知道你说的线程安全是不是还是加锁实现的,还是有其他方案。
> 如果是加锁的话,线程安全和不安全的区别反倒可以模糊,不跨线程的使用自然是安全的,跨线程使用时加锁。使用同一内存池也就可以了,还避免了copy。
> 除非当我跨线程使用线程不安全数据时你可以自动帮我处理到线程安全池。
>
> --------------------------------------------------
> From: "sunway" <sunhui...@gmail.com>

gamemake

unread,
Jul 29, 2008, 11:46:16 AM7/29/08
to 高性能网络编程邮件列表
svn co https://sailing.googlecode.com/svn/trunk/framework
上面是我正在写的一个framework, 还没有写完.现在里面大部分东西都是上个项目中写的.
mempool.c 就是我实现的裁剪版mempool

xmatrix

unread,
Aug 4, 2008, 4:02:05 AM8/4/08
to 高性能网络编程邮件列表
“很多时候,线程安全的线程池,即使是使用无锁数据结构,其效率也不一定比系统提供的malloc高多少。 ”
对于预分配内存池来说,比系统分配快的不是一点两点。

On 7月25日, 下午4时19分, esx <nay...@gmail.com> wrote:
> > - Show quoted text -- 隐藏被引用文字 -
>
> - 显示引用的文字 -

xmatrix

unread,
Aug 4, 2008, 5:37:08 AM8/4/08
to 高性能网络编程邮件列表
测试了才知道,想是是不可能能知道的。实际上,系统的分配本身就是带锁的,因为你可能在多个线程中调用new,delete。一般来说,使用池总比系统
的快,这方面的算法不少。

On 7月25日, 下午4时24分, christanxw <christa...@gmail.com> wrote:
> > - 显示引用的文字 -- 隐藏被引用文字 -
>
> - 显示引用的文字 -

esx

unread,
Aug 5, 2008, 12:03:29 AM8/5/08
to 高性能网络编程邮件列表
这恐怕和OS本身还有一些出入,我这里的一些经验数据貌似是,一般预分配的单线程的不上锁的内存池比系统的要快50%左右,但是上锁的,可能就快10%
左右甚至可能会低于此。

另外值得一提的是,当前的OS(Linux、FreeBSD、Solaris)都使用了类似slab这种内存分配方式,类似内存池,换句话说,OS已经
实现了一个稳健的、线程安全的内存池。所以如果用户再实现一个加锁的内存池,可能会有些画蛇添足(引发的bug、甚至是性能问题)。不过这要看具体需求
来决定是否真的需要用内存池来提高性能了。

大家可以提供一些参考数据说一下?;)
> > - 显示引用的文字 -- Hide quoted text -

sunway

unread,
Aug 11, 2008, 3:39:27 AM8/11/08
to 高性能网络编程邮件列表
具体,你可以自己测试下,用C/c++运行库的 new malloc 和自己的内存分配器

xmatrix

unread,
Aug 11, 2008, 4:26:14 AM8/11/08
to 高性能网络编程邮件列表
我想,似乎不必争论池是否比系统提供的分配函数快还是慢,关键是看你的需求和池的实作。一些有名的库里就提供了这些池,比如
boost,loki,SGI-STL,C++之父的书TCPL里也提供了一个固定大小的内存块分配池,其中效率快慢大家不言自明。

On 8月5日, 下午12时03分, esx <nay...@gmail.com> wrote:

Linker Lin

unread,
Apr 6, 2009, 11:02:44 AM4/6/09
to dev4s...@googlegroups.com
vc的内存分配很慢,gcc快的多。

--
Sent from my mobile device

Linker M Lin
linke...@gmail.com
※※※※※※※※※
※※我思故我在※※
※※※※※※※※※

kennywong

unread,
Apr 6, 2009, 11:16:48 AM4/6/09
to 高性能网络编程邮件列表

对于一些转发式的服务器,实现一种线程安全,又可以减少加锁次数的固定大小分配内存池的可能是存在的.


实现方案如下,接收线程接收到包后,由线程内存池分配一块内存,然后直接将指针传到转发线程发送.发送
完毕后,将内存块放回属于本线程的线程池.当任一内存池发觉预分配内存块不够时,才执行一次同步工作,将
其它线程池中的一部分固定内存块同步到本地内存池。

则加锁操作,仅仅会出现在本地线程池固定内存块不足的情况下.

kennywong

unread,
Apr 6, 2009, 11:21:13 AM4/6/09
to 高性能网络编程邮件列表
对于转发式服务器,接收线程所分配的固定内存,最终都会流到转发线程中.

所以当接收线程的内存池中内存块不够时,可直接向转发线程索要即可,一次加锁将一整片内存块同步过来.以后继续分配内存,就无需要再加锁了.

Reply all
Reply to author
Forward
0 new messages