高效服务器开发中,关于内存操作的疑惑。求解!

rabo 2007-06-18 06:46:14
我设计了一个服务器,使用IOCP模式。

在处理服务器接收数据的地方,遇到了一些问题。

比如我先收到包头,发现要收的数据为1024个字节,这个时候我就new出来这个空间,然后收一次,拷进去一次,N次之后,拷满了,确定这个逻辑包收完了,我才开始交给上层处理数据。

目前我是上述这样实现的。但这就引发了几个问题。

1,连接数比如有1000个,那么,比如每个数据大小为1M,那我就要NEW 1000M的内存来等拷贝。
2,1000个连接后,比如一个连接要memcpy 10次,那么就是10000次,效率很低。
3,实际应用中,小数据比较多,而且我不停的NEW,内存碎片就越来越多。

总结一下,就是性能低下。

但是现在在运营中的那么多服务器不都很高效吗?能上万连接。
那一定就是我在设计这方面知识比较落后,但在网上查了又查,网上也没说个什么名堂出来。
特来此求教!

希望朋友们讲一下,你们是怎么样设计的。我用心学习一下。谢谢大家了。
...全文
596 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
simon031187 2007-07-18
  • 打赏
  • 举报
回复
可以在申请内存的时候按照一定的规格来申请。
比如以XX个BYTE为单位,小于XX个的的也分配这么多,大于的就申请多个内存区。
这样产生的内存碎片都是一样大小,方便系统再分配。
rabo 2007-07-18
  • 打赏
  • 举报
回复
谢谢大家,我出差快出了一个月了。终于回来了。按照大家的说法,看了一些资料,应该我的系统的瓶颈就在内存管理上了。谢谢。
吴双1983 2007-06-27
  • 打赏
  • 举报
回复
想开点。1000个同时在连接已经是一个很大的项目了。硬件肯定要求要高点了。
leon7909 2007-06-27
  • 打赏
  • 举报
回复
内存分配使用内存池,内存的组织的话参考TCP/IP协议栈里的mbuf以避免memcpy的动作。
nizhaorong 2007-06-27
  • 打赏
  • 举报
回复
避免频繁申请与释放
nizhaorong 2007-06-27
  • 打赏
  • 举报
回复
写一个内存管理类
xyxfly 2007-06-26
  • 打赏
  • 举报
回复
我们目前也是使用内存池~~
Hylas 2007-06-26
  • 打赏
  • 举报
回复
根据需求先分配 足够大的, 万一峰值时候不够用,再动态分配放入池中
rulera 2007-06-26
  • 打赏
  • 举报
回复
upup
danscort2000 2007-06-26
  • 打赏
  • 举报
回复
内存池比较慢的,现在的开发一般都不再使用了
我感觉你的结构有问题,
为什么要使用1M内存的缓冲对应一个连接?
数据量有这么大吗?
你的网络传输数据结构是怎么样的?
就算是网络游戏或者文件传输,我感觉也不需要这么大的内存缓冲啊
enterprise54 2007-06-25
  • 打赏
  • 举报
回复
关于组包,LZ没有必要为每个socket都分配1M的组装缓冲区,你可以IO工作线程分配一个缓冲区,然后在线程被唤醒的时候开始进行组包操作。如果工作线程只有5个话,即使有10000个连接,组装缓冲区也只有5M的,而不是10000M。对异步投递的IO操作缓冲区,最好是用内存池来操作,比如你在内存池中预分配1000个异步IO操作包,一旦出现了异步IO操作包被利用完的时候,后面的操作就需要挂起,等前面的IO操作包完成后再分配。
rabo 2007-06-25
  • 打赏
  • 举报
回复
大家好,我出差回来了,累死了。我先用内存池试试,但是不知道内存池要分多大。怕分小了,系统挂起的就多了,分大了,占用太大。
zdleek 2007-06-20
  • 打赏
  • 举报
回复
楼主对IOCP的使用方法好像掌握的不够,建议看看相关资料,下载网上的源代码来研究一下,
windows下IOCP是做大量连接服务的最好方案之一
DentistryDoctor 2007-06-19
  • 打赏
  • 举报
回复
memory pool
csy_2002 2007-06-19
  • 打赏
  • 举报
回复
我现在就是自己建的一个内存池,不用的内存放到一个表里面去;需要内存块的时候,从表里面获取
rabo 2007-06-19
  • 打赏
  • 举报
回复
谢谢大家,大家的意思都是使用内存池,我因为在外出差,所以这几天很难上网。我研究一下,请大家继续讨论。
Hylas 2007-06-19
  • 打赏
  • 举报
回复
请教 忘掉她好难 限制未分页内存锁定失败的可能

是如何产生, 产生后应该怎么解决?
Hylas 2007-06-19
  • 打赏
  • 举报
回复
所谓内存池,就是事先静态分配好的内存, 然后,根据需要 提取一块内存空间使用,
使用完毕之后放回。 内存区域管理 做好多线程保护。
如果很大的数据包,建议做业务包打碎处理

内存拷贝在性能要求高的地方 是要求尽量少, 但有时候不得 还是要做的。
内存动态分配消耗的时间 主要在于 释放的时间

你可以试验一下 1万次 copy 1k数据需要时间 ,和释放1万次需要的时间。
enterprise54 2007-06-19
  • 打赏
  • 举报
回复
除了使用内存池之外,LZ还需要限制未分页内存锁定失败的可能,一旦出现了这样的错误,服务器一般就会崩溃。最好需要限制投递异步操作的数量!
僵哥 2007-06-18
  • 打赏
  • 举报
回复
可以自己手动建议一个或多个内存池,然后进行内存重用,不过建议每次分配的满页内存,我正好前天晚上也做了类似的测试,连续分配1GB,然后释放掉,如此让程序运行了14小时,最后只是比起动的时候多用了一兆左右的内存(在任务管理器当中看到的,有可能是列表对象自身形成的碎片或者其它)。

不过我觉得楼主仅仅只是使用一种想当然的方式考虑问题。就算你每次发起4k的接收缓冲区,以百兆网络为例,大概每秒能收发的报文是总量大概是3k个,对于1MB数据,就算你一秒钟才收到一个包,那也就是在256秒后收完,如此计算大概需要3G的缓冲。而这个时候,这个服务的并发量几乎达到3k,就算是高压力(只有压力测试的时候才会产生)的服务下,那么这需要至少3万以上的在线量。而对于3万的在线量处理能力的服务器难道没有3G内存的配置?而对于上4M的数据,难道全部单纯依赖于内存进行存储?而且每个连接4MB的数据,每秒并发处理有接近300个,CPU资源在这个数据处理和网络报文处理当中平衡之后还能达到多少的流量?

这问题纯粹只是楼主自己多余的担心。
加载更多回复(4)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧