IOCP模型接收文件CPU占用率奇高

breaddawson 2006-05-29 08:31:56
做了一个传送文件的小程序
用TCP的socket

client端就是用最简单的send函数,每8*1024字节一次,发送到server端

server端本来直接recv接收,这样在传送文件途中,CPU使用率大概有20%

看到IOCP模型性能比较好
于是研究了一下,把server端改成IOCP模型

可是改了以后,传送文件途中CPU占用率一直都几乎到达100%,有时候会突然变小,但又快速提高

郁闷中,难道IOCP模型名不副实?

怀疑是频繁申请内存空间的问题,(因为server端要不停申请per-I/O资源),后来采用重用以后,问题依旧

然后怀疑是写文件的问题,所以把写文件语句屏蔽,也就是只收不写,CPU占用率依旧

那么问题似乎只剩下一个,就是GetQueuedCompletionStatus的问题了
我用的是GetQueuedCompletionStatus(Completion,&dwTrans,&dwKey,
(LPOVERLAPPED *)&lpol,WSA_INFINITE)
等待时间是WSA_INFINITE
而且只要不传文件,CPU就正常,一传文件,就居高不下
所以是不是可以怀疑是这个函数的问题?

弄了两天了,测试了无数遍
实在找不到原因了
请各路高手帮忙分析一下
看还有什么可能的原因啊?
...全文
683 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
danscort2000 2006-12-21
  • 打赏
  • 举报
回复
其实网络文件传输,和你采用什么模型根本没有关系
IOCP出来的时间不长,绝大多数的文件服务器都没有采用IOCP,而是采用最原始的非阻塞SOCKET,IOCP底层还是需要调用SOCKET函数执行的(WSA。。。。)
IOCP的是利用了操作系统的IO完成时通知机制,和传输和如何传输并没有直接的关系
出现CPU占用高的问题,一般是你的代码问题
例如在DEBUG模式下,你调用的IOCP函数会有大量的ASSERT VERIFY,影响效率
另外那个ZeroMemory函数也是非常耗费资源的,你还需要注意缓冲大小,缓冲太小
会导致过于频繁调用申请-》填充-》发送过程,CPU也会奇高
KeSummer 2006-12-21
  • 打赏
  • 举报
回复
嘿嘿~学习一下~
templarzq 2006-12-21
  • 打赏
  • 举报
回复
zeromemory是一个非常占资源的操作....以前也有人出现过这样的问题.去了吧
Fly_1101 2006-12-21
  • 打赏
  • 举报
回复
你在WSARecv时WSABUF的buf的大小是多少?
如果比你send的长度8*1024小很多,那么一次send就会要很多次WSARecv才能完成,CPU的占用率自然就上去了,如果是这样,把WSABUF的buf也改成8*1024试试
Qeim 2006-12-20
  • 打赏
  • 举报
回复
在Client的send的地方加个Sleep(10),就可以了,但这会降低传送效率,我以前遇到过类似的,没加Sleep 2-5M/s的速度,加了之后800-1100K/s了,缓冲区是1024*10 呵呵
sirguan 2006-06-09
  • 打赏
  • 举报
回复
肯定是代码的问题,不用怀疑,呵呵
sdf123321 2006-06-09
  • 打赏
  • 举报
回复
gz
MuseIn 2006-05-30
  • 打赏
  • 举报
回复
code ?
萧山夜雨 2006-05-30
  • 打赏
  • 举报
回复
贴出的是部分代码。文件操作没问题吧?
萧山夜雨 2006-05-30
  • 打赏
  • 举报
回复
肯定是你程序的问题,我100Mbps的吞吐率时,CPU才60% 网卡利用99% IOCP传数据速度奇快。
breaddawson 2006-05-29
  • 打赏
  • 举报
回复
晕,看来每一个连接就要占到30%的CPU
开了两个,结果CPU大概稳定在60%
不知道这个占用率正常不正常啊
breaddawson 2006-05-29
  • 打赏
  • 举报
回复
把::ZeroMemory(pBuffer,sizeof(IOCPBUFFER));一句去掉
CPU占用率下降到30%左右
请问这样正常不正常啊
我这还只是一个客户端
我再多弄几个客户端,一起传,试试看
一会上来汇报结果
breaddawson 2006-05-29
  • 打赏
  • 举报
回复
我也怀疑是代码的问题
可是针对各个地方调试了好多次
实在是没辄了

这是workerthread里无限循环GetQueuedCompletionStatus后分支语句里接收的部分
文件传输时不停调用的只有这一块
请各位帮忙看一下,我加了些注释
谢谢了


//如果完成的是接收请求
if (pBuffer->nOperation==FT_RECV)
{

//如果接收到数据为0
if (dwTrans==0)
{
printf ("no data \n");
return -1;
}
pBuffer->nBuffLen=dwTrans;

//文件总大小,pContext是单句柄数据,里面的文件大小和文件名是
//AccpetEx成功后得到的第一块数据得来的
int iTotal=pContext->FileTask.dwLength;
//当前要写入的文件位置,nCurrentReadSequence是当前要读
int iCurrent=(pBuffer->nSequenceNumber-1)*BUFFER_SIZE;
ofstream os;


//同时只允许一个线程操作文件对象
::EnterCriticalSection(&pContext->Lock);

if (iCurrent==0)
os.open(pContext->FileTask.szFileName,ios::binary);
else
os.open(pContext->FileTask.szFileName,ios::binary | ios::app);
os.seekp(iCurrent,ios::beg);
os.write(pBuffer->sBuff,pBuffer->nBuffLen);
os.close();


::LeaveCriticalSection(&pContext->Lock);


//如果还需要再投递
//nNextPostSeqence是下一个要投递的WSARecv请求的序号
//根据这个和nTotalPackets总包号对照,判断要不要继续投放
if (pContext->nNextPostSeqence<=pContext->nTotalPackets)
{
//重用pBuffer
::ZeroMemory(pBuffer,sizeof(IOCPBUFFER));
pBuffer->sBuff=(char *)(pBuffer+1);
pBuffer->nBuffLen=BUFFER_SIZE;
ft->PostRecv(pContext,pBuffer);
}
//如果已经全部接收完毕
if (pContext->nCurrentReadSequence==pContext->nTotalPackets)
{
::HeapFree(::GetProcessHeap(), 0, pContext);
::HeapFree(::GetProcessHeap(), 0, pBuffer);
printf ("File Completed\n");
}
//成功得到数据,当前要读的数据包序号加一
::InterlockedIncrement((LONG *)&pContext->nCurrentReadSequence);
}
_____non______ 2006-05-29
  • 打赏
  • 举报
回复
肯定是你的代码有问题~~~

没有必要为了每一个操作分配一块内存~~

一个Socket分配2块内存即可,一个是接收,一个是发送,如果想要提高效率,可以再分配2块内存,做为发送和接收的缓冲区
DentistryDoctor 2006-05-29
  • 打赏
  • 举报
回复
IOCP的性能的确高,尤其在高并发的情况下。
如果你的程序CPU占用不正常的高,只能说明你的代码有问题。

18,357

社区成员

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

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