为什么我写文件的时候CPU占用率达100%,请大家帮我看看(附源码)。(50分)

  • 主题发起人 主题发起人 ansili
  • 开始时间 开始时间
A

ansili

Unregistered / Unconfirmed
GUEST, unregistred user!
这是写文件的一个线程,数据是从Socket上来的,收到数据放入待写队列。<br>这个线程负责将待写队列的数据写到文件中去,下面是写文件的方法。<br><br>麻烦帮我看看,谢谢!<br><br>procedure ProcReceiveHistoryThread.proReceiveHisData(<br> &nbsp;AMsgRecieveHisData: MyBodyReceiveHisData; ABuffer: PChar;<br> &nbsp;ALength: integer);<br>var<br> &nbsp;filename : String;<br> &nbsp;FileHandle : Integer;<br> &nbsp;st,et : Cardinal;<br> &nbsp;curLength : Cardinal;<br> &nbsp;msgRecvHisData : MyReceiveHistoryData;<br>begin<br> &nbsp;st := GetTickCount;<br> &nbsp;filename := DataPath + AMsgRecieveHisData.file_name;<br> &nbsp;FillChar(msgRecvHisData,SizeOf(MyReceiveHistoryData),0);<br> &nbsp;if FileExists(filename) then<br> &nbsp;begin<br> &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp;FileHandle := FileOpen(filename,fmOpenReadWrite or fmShareDenyWrite);<br> &nbsp; &nbsp; &nbsp;FileRead(FileHandle,msgRecvHisData,SizeOf(MyReceiveHistoryData));<br> &nbsp; &nbsp; &nbsp;if msgRecvHisData.current_length &lt; msgRecvHisData.total_length then<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;msgRecvHisData.total_length := AMsgRecieveHisData.total_length;<br> &nbsp; &nbsp; &nbsp; &nbsp;msgRecvHisData.current_length := msgRecvHisData.current_length + SizeOf(Cardinal) + ALength;<br> &nbsp; &nbsp; &nbsp; &nbsp;curLength := FileSeek(FileHandle,0,0);<br> &nbsp; &nbsp; &nbsp; &nbsp;FileWrite(FileHandle,msgRecvHisData,SizeOf(MyReceiveHistoryData));<br> &nbsp; &nbsp; &nbsp; &nbsp;//写数据部分<br> &nbsp; &nbsp; &nbsp; &nbsp;curLength := FileSeek(FileHandle,0,2);<br> &nbsp; &nbsp; &nbsp; &nbsp;FileWrite(FileHandle,ALength,SizeOf(integer));<br> &nbsp; &nbsp; &nbsp; &nbsp;FileWrite(FileHandle,ABuffer[0],ALength);<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp;finally<br> &nbsp; &nbsp; &nbsp;FileClose(FileHandle);<br> &nbsp; &nbsp;end;<br> &nbsp;end;<br> &nbsp;et := GetTickCount;<br> &nbsp;//AppendLog('=======写历史文件消耗时间: ' + FloatToStr((et-st)/1000));<br>end;
 
加上 &nbsp;Application.ProcessMessages ;<br>看看
 
这位同学,你好像忘加sleep(1)了,不然它会把所有的系统资源吃光的[:D]
 
Application.ProcessMessages <br>肯定不行,我这个线程和界面是没有关系的。<br>加上sleep(1)这个CPU使用率是降低了,但是写文件的速度却慢了很多。<br><br>怎么可以写文件速度很快,且CPU消耗比较低(60%)。
 
我在想读和写各开一个线程,然后适当的加上sleep,是否会好些呢?
 
作个缓存<br>FileWrite尽量少调用,将ABuffer先写入一个内存里,然后,堆积到一定数量再一次性写入文件.<br>这样试下.<br><br>还有,将文件的打开,关闭放到外循环中,也就是不是每次调用那函数你就打开关闭,浪费.<br><br>这两项做了还是CPU很高的话,你再将线程主循环调用发过来看看
 
To : errorcode<br>我保存文件是根据接收到的文件名去确定写到那个文件,所以就要现在这样的打开操作。<br>我现在按你说‘将文件的打开,关闭放到外循环中’来试试。<br><br>还有你说‘FileWrite尽量少调用’那我现在的方式应该用什么方法去写文件呢?用这个TFileStream?
 
To : errorcode<br>我现在按你说‘将文件的打开,关闭放到外循环中’还是消耗很高。<br>下面是我整个线程的代码:<br>//*********************************<br>// &nbsp;处理请求的历史数据<br>// &nbsp;Ansili 2006-10-10<br>//********************************<br>unit unitProcReceiveHistoryThread;<br><br>interface<br><br>uses<br> &nbsp;Classes, Windows, SysUtils, Contnrs, SyncObjs,<br> &nbsp;unitDataModule, unitGlobalStructure;<br><br>type<br> &nbsp;ProcReceiveHistoryThread = class(TThread)<br> &nbsp;private<br> &nbsp; &nbsp;Port : Word;<br> &nbsp; &nbsp;DataPath : String;<br> &nbsp; &nbsp;{ Request History Data }<br> &nbsp; &nbsp;RequestQueue &nbsp; &nbsp;: TQueue;<br> &nbsp; &nbsp;RequestQueueEvent : TEvent;<br> &nbsp; &nbsp;RequestQueueSection : TCriticalSection;<br><br> &nbsp; &nbsp;SaveFileName : String;<br> &nbsp; &nbsp;SaveFileHandle : Integer;<br> &nbsp; &nbsp;SaveFileStream : TFileStream;<br> &nbsp; &nbsp;<br> &nbsp; &nbsp;procedure FreeLocalVariant(Sender : TObject);<br> &nbsp; &nbsp;procedure proBuffer(const ALength : Integer; const ABuffer : PChar);<br> &nbsp; &nbsp;procedure proReceiveHisData(AMsgRecieveHisData: MyBodyReceiveHisData;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ABuffer : PChar;ALength : integer);<br> &nbsp; &nbsp;procedure proSaveHistoryFile(AMsgRecieveHisData: MyBodyReceiveHisData;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ABuffer : PChar;ALength : integer);<br> &nbsp;protected<br> &nbsp; &nbsp;procedure Execute; override;<br> &nbsp;public<br> &nbsp; &nbsp;constructor Create(ACreateSuspended: Boolean = True); virtual;<br> &nbsp; &nbsp;procedure SetRequestQueue(AQueue: TQueue);<br> &nbsp; &nbsp;procedure SetRequestQueueEvent(AQueueEvent: TEvent);<br> &nbsp; &nbsp;procedure SetRequestQueueSection(AQueueSection: TCriticalSection);<br> &nbsp; &nbsp;procedure SetPort(APort : Word);<br> &nbsp; &nbsp;function &nbsp;GetThreadStatus : Boolean;<br> &nbsp;end;<br><br>implementation<br><br>uses unitGlobalSet;<br><br>{ ProcReceiveHistoryThread }<br><br>constructor ProcReceiveHistoryThread.Create(ACreateSuspended: Boolean);<br>begin<br> &nbsp;inherited Create(ACreateSuspended);<br> &nbsp;OnTerminate := FreeLocalVariant;<br> &nbsp;FreeOnTerminate := true;<br><br> &nbsp;SaveFileHandle := -1;<br> &nbsp;SaveFileStream := nil;<br> &nbsp;DataPath := GlobalWorkInfo.DataPath;<br>end;<br><br>procedure ProcReceiveHistoryThread.FreeLocalVariant(Sender: TObject);<br>begin<br> &nbsp;if SaveFileStream &lt;&gt; nil then<br> &nbsp;begin<br> &nbsp; &nbsp;FreeAndNil(SaveFileStream);<br> &nbsp;end;<br> &nbsp;AppendLog('终止历史数据保存线程 ProcReceiveHistoryThread');<br>end;<br><br>function ProcReceiveHistoryThread.GetThreadStatus: Boolean;<br>begin<br> &nbsp;Result := Self.Terminated;<br>end;<br><br>procedure ProcReceiveHistoryThread.SetPort(APort: Word);<br>begin<br> &nbsp;Port := APort;<br>end;<br><br>procedure ProcReceiveHistoryThread.SetRequestQueue(AQueue: TQueue);<br>begin<br> &nbsp;RequestQueue := AQueue;<br>end;<br><br>procedure ProcReceiveHistoryThread.SetRequestQueueEvent(<br> &nbsp;AQueueEvent: TEvent);<br>begin<br> &nbsp;RequestQueueEvent := AQueueEvent;<br>end;<br><br>procedure ProcReceiveHistoryThread.SetRequestQueueSection(<br> &nbsp;AQueueSection: TCriticalSection);<br>begin<br> &nbsp;RequestQueueSection := AQueueSection; <br>end;<br><br>procedure ProcReceiveHistoryThread.Execute;<br>var<br> &nbsp;DataBuf : TMyDataBuffer;<br>begin<br> &nbsp;FreeOnTerminate := true;<br> &nbsp;while(not Terminated)do<br> &nbsp;begin<br> &nbsp; &nbsp;if(RequestQueue.Count &lt;= 0) then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;RequestQueueEvent.ResetEvent;<br> &nbsp; &nbsp; &nbsp;RequestQueueEvent.WaitFor(INFINITE);<br> &nbsp; &nbsp;end<br> &nbsp; &nbsp;else<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;DataBuf := nil;<br> &nbsp; &nbsp; &nbsp;RequestQueueSection.Enter;<br> &nbsp; &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp; &nbsp;DataBuf := TMyDataBuffer(RequestQueue.Pop);<br> &nbsp; &nbsp; &nbsp;except on Ex : Exception do<br> &nbsp; &nbsp; &nbsp; &nbsp;AppendLog(IntToStr(Port) + ': ProcReceiveHistoryThread Pop Queue Error : ' + Ex.Message);<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp;RequestQueueSection.Leave;<br> &nbsp; &nbsp; &nbsp;if DataBuf &lt;&gt; nil then<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;proBuffer(DataBuf.BufferLength,DataBuf.BufferData);<br> &nbsp; &nbsp; &nbsp; &nbsp;except on Ex : Exception do<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;AppendLog(IntToStr(Port) + ': ProcReceiveHistoryThread DoBuffer Error : ' + Ex.Message);<br> &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FreeAndNil(DataBuf);<br> &nbsp; &nbsp; &nbsp; &nbsp;except on Ex : Exception do<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;AppendLog(IntToStr(Port) + ': ProcReceiveHistoryThread,FreeAndNil(DataBuf) Error : ' + Ex.Message);<br> &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp;end;<br> &nbsp;end;<br>end;<br><br>procedure ProcReceiveHistoryThread.proBuffer(const ALength: Integer;<br> &nbsp;const ABuffer: PChar);<br>var<br> &nbsp;i : &nbsp;integer;<br> &nbsp;tmpLen, len : integer;<br> &nbsp;ErrorStr &nbsp; &nbsp; : String;<br> &nbsp;DataFlag &nbsp; &nbsp; : Cardinal;<br> &nbsp;MsgHeader &nbsp; &nbsp;: MyMessageHeader; &nbsp; &nbsp; &nbsp; //消息头<br> &nbsp;MsgRecieveHisData: MyBodyReceiveHisData; &nbsp;//接收请求的历史数据<br> &nbsp;DataBuffer : PChar;<br>begin<br> &nbsp;i := 0; &nbsp;//指针位置<br> &nbsp;if i + SizeOf(Cardinal) &gt; ALength then<br> &nbsp;begin<br> &nbsp; &nbsp;Exit;<br> &nbsp;end;<br> &nbsp;tmpLen := 0;<br> &nbsp;DataFlag := 0;<br> &nbsp;Move(ABuffer,DataFlag ,SizeOf(Cardinal));<br> &nbsp;if DataFlag &lt;&gt; MY_MESSAGE_FLAG then &nbsp;//判断标志位<br> &nbsp;begin<br> &nbsp; &nbsp;Exit;<br> &nbsp;end;<br> &nbsp;i := i + SizeOf(Cardinal);<br> &nbsp;//读取消息头<br> &nbsp;if i + SizeOf(MyMessageHeader) &gt; ALength then<br> &nbsp;begin<br> &nbsp; &nbsp;Exit;<br> &nbsp;end;<br> &nbsp;Move(ABuffer,MsgHeader,SizeOf(MyMessageHeader));<br> &nbsp;i := i + SizeOf(MyMessageHeader);<br> &nbsp;case MsgHeader.message_type of<br> &nbsp; &nbsp;204 : if (i + SizeOf(MyBodyReceiveHisData)) &lt; ALength then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Move(ABuffer,MsgRecieveHisData,SizeOf(MyBodyReceiveHisData));<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;i := i + SizeOf(MyBodyReceiveHisData);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;len := MsgRecieveHisData.length;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((i + len) = ALength) and (len &gt; 0) then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DataBuffer := AllocMem(len);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Move(ABuffer,DataBuffer[0],len);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;i := i + len;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//proReceiveHisData(MsgRecieveHisData,DataBuffer,len);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;proSaveHistoryFile(MsgRecieveHisData,DataBuffer,len);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;except on Ex : Exception do<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;AppendLog(IntToStr (Port) + ': ProcReceiveHistoryThread,DoDataTransfer Error : ' + Ex.Message);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;finally<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FreeMem(DataBuffer);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp;end;<br>end;<br><br>procedure ProcReceiveHistoryThread.proReceiveHisData(<br> &nbsp;AMsgRecieveHisData: MyBodyReceiveHisData; ABuffer: PChar;<br> &nbsp;ALength: integer);<br>var<br> &nbsp;filename : String;<br> &nbsp;FileHandle : Integer;<br> &nbsp;curLength : Cardinal;<br> &nbsp;msgRecvHisData : MyReceiveHistoryData;<br>begin<br> &nbsp;filename := DataPath + AMsgRecieveHisData.file_name;<br> &nbsp;FillChar(msgRecvHisData,SizeOf(MyReceiveHistoryData),0);<br> &nbsp;if FileExists(filename) then<br> &nbsp;begin<br> &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp;FileHandle := FileOpen(filename,fmOpenReadWrite or fmShareDenyWrite);<br> &nbsp; &nbsp; &nbsp;FileRead(FileHandle,msgRecvHisData,SizeOf(MyReceiveHistoryData));<br> &nbsp; &nbsp; &nbsp;if msgRecvHisData.current_length &lt; msgRecvHisData.total_length then<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;msgRecvHisData.total_length := AMsgRecieveHisData.total_length;<br> &nbsp; &nbsp; &nbsp; &nbsp;msgRecvHisData.current_length := msgRecvHisData.current_length + SizeOf(Cardinal) + ALength;<br> &nbsp; &nbsp; &nbsp; &nbsp;curLength := FileSeek(FileHandle,0,0);<br> &nbsp; &nbsp; &nbsp; &nbsp;FileWrite(FileHandle,msgRecvHisData,SizeOf(MyReceiveHistoryData));<br> &nbsp; &nbsp; &nbsp; &nbsp;//写数据部分<br> &nbsp; &nbsp; &nbsp; &nbsp;curLength := FileSeek(FileHandle,0,2);<br> &nbsp; &nbsp; &nbsp; &nbsp;FileWrite(FileHandle,ALength,SizeOf(integer));<br> &nbsp; &nbsp; &nbsp; &nbsp;FileWrite(FileHandle,ABuffer[0],ALength);<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp;finally<br> &nbsp; &nbsp; &nbsp;FileClose(FileHandle);<br> &nbsp; &nbsp;end;<br> &nbsp;end;<br>end;<br><br>procedure ProcReceiveHistoryThread.proSaveHistoryFile(<br> &nbsp;AMsgRecieveHisData: MyBodyReceiveHisData; ABuffer: PChar;<br> &nbsp;ALength: integer);<br>var<br> &nbsp;filename : String;<br> &nbsp;FileHandle : Integer;<br> &nbsp;curLength : Cardinal;<br> &nbsp;msgRecvHisData : MyReceiveHistoryData;<br>begin<br> &nbsp;filename := DataPath + AMsgRecieveHisData.file_name;<br> &nbsp;if SaveFileName &lt;&gt; filename then<br> &nbsp;begin<br> &nbsp; &nbsp;if SaveFileStream &lt;&gt; nil then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;FreeAndNil(SaveFileStream);<br> &nbsp; &nbsp;end;<br> &nbsp; &nbsp;SaveFileName := DataPath + AMsgRecieveHisData.file_name;<br> &nbsp; &nbsp;SaveFileStream := TFileStream.Create(SaveFileName,fmOpenReadWrite or fmShareDenyWrite);<br> &nbsp;end;<br> &nbsp;FillChar(msgRecvHisData,SizeOf(MyReceiveHistoryData),0);<br> &nbsp;if FileExists(SaveFileName)and(SaveFileStream &lt;&gt; nil) then<br> &nbsp;begin<br> &nbsp; &nbsp;SaveFileStream.Position := 0;<br> &nbsp; &nbsp;SaveFileStream.ReadBuffer(msgRecvHisData,SizeOf(MyReceiveHistoryData));<br> &nbsp; &nbsp;if msgRecvHisData.current_length &lt; msgRecvHisData.total_length then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;msgRecvHisData.total_length := AMsgRecieveHisData.total_length;<br> &nbsp; &nbsp; &nbsp;msgRecvHisData.current_length := msgRecvHisData.current_length + SizeOf(Cardinal) + ALength;<br> &nbsp; &nbsp; &nbsp;SaveFileStream.Position := 0;<br> &nbsp; &nbsp; &nbsp;SaveFileStream.WriteBuffer(msgRecvHisData,SizeOf(MyReceiveHistoryData));<br> &nbsp; &nbsp; &nbsp;//写数据部分<br> &nbsp; &nbsp; &nbsp;SaveFileStream.Position := SaveFileStream.Size;<br> &nbsp; &nbsp; &nbsp;SaveFileStream.WriteBuffer(ALength,SizeOf(integer));<br> &nbsp; &nbsp; &nbsp;SaveFileStream.WriteBuffer(ABuffer[0],ALength);<br> &nbsp; &nbsp;end;<br> &nbsp;end;<br>end;<br><br>end.
 
看用在我的文件传输系统中的的缓冲写文件方式,多任务占用CUP不超过10%,100M局域网能达到13M~16M/S的速度。<br>接收文件的函数<br>===============================================================================<br>procedure TFileSvr.DoUpFileData(ClientThread: TDXClientThread);<br>var<br> &nbsp;i: Integer;<br> &nbsp;lUserbuff: TUserSubTread;<br> &nbsp;Lbuff: RUpFileData;<br> &nbsp;Lidx: Integer;<br> &nbsp;LOpter: TFileItem;<br> &nbsp;LRecSize, LCurrRec, LTrueSize: Int64;<br> &nbsp;LRecBuff: Pointer;<br>begin<br> &nbsp;LRecBuff := nil;<br> &nbsp;lUserbuff := TUserSubTread.Create;<br> &nbsp;lUserbuff.Conn := ClientThread;<br> &nbsp;ClientThread.fpSessionData := lUserbuff;<br> &nbsp;ClientThread.Socket.ReceiveBuf(Lbuff, Sizeof(Lbuff));<br> &nbsp;{用户线程开始上传}<br> &nbsp;lUserbuff.WriteRd := Lbuff;<br> &nbsp;Lidx := FileUoDMM.LockList.IndexOf(IntToStr(lbuff.FileID));<br> &nbsp;if Lidx &lt; 0 then begin<br> &nbsp; &nbsp;Dec(tuser(ClientThread.fpSessionData).SubThreadCount);<br> &nbsp; &nbsp;Shower.AddShow('严重错误,未发现此文件任务 文件ID%D', [lbuff.FileID]);<br> &nbsp; &nbsp;Exit;<br> &nbsp;end<br> &nbsp;else begin<br> &nbsp; &nbsp; &nbsp;{加入到FileItem的线程列表内}<br> &nbsp; &nbsp;TFileItem(FileUoDMM.PeekItem(Lidx)).FileOptList.AddObject(Format('%d_%d', [Lbuff.StartPos, Lbuff.EndPos]), lUserbuff);<br> &nbsp;end;<br> &nbsp;LOpter := TFileItem(FileUoDMM.PeekItem(Lidx));<br> &nbsp;LOpter.CheckTime := GetTickCount;<br> &nbsp;Shower.AddShow('开始发送数据 文件ID:%D 起始:%d 到:%d', [Lbuff.FileID, Lbuff.StartPos, Lbuff.EndPos]);<br> &nbsp;if InRange(Lbuff.StartPos, 0, LOpter.fileSize) = False then begin<br> &nbsp; &nbsp;Shower.AddShow('上传的标示不在范围内', []);<br> &nbsp; &nbsp;{如果上传的标示不在范围内}<br> &nbsp; &nbsp;Dec(Tuser(ClientThread.fpSessionData).SubThreadCount);<br> &nbsp; &nbsp;ClientThread.fpSessionData := nil;<br> &nbsp; &nbsp;ClientThread.Socket.Disconnect;<br> &nbsp;end;<br> &nbsp;try<br> &nbsp; &nbsp;try<br> &nbsp; &nbsp; &nbsp;lUserbuff.ConnToFile(LOpter.FileName, fmOpenWrite);<br> &nbsp; &nbsp; &nbsp;LRecBuff := GetMemory(1024 * 8);<br> &nbsp; &nbsp; &nbsp;LRecSize := Lbuff.EndPos - Lbuff.StartPos; {总共要读取的大小}<br> &nbsp; &nbsp; &nbsp;LCurrRec := 0; {已经读取的大小}<br> &nbsp; &nbsp; &nbsp;LTrueSize := Min(1024 * 8, LRecSize - LCurrRec);<br> &nbsp; &nbsp; &nbsp;SetBuff(lUserbuff.PCurrRecvBUff, CMissonRecBuff + 1024 * 8);<br> &nbsp; &nbsp; &nbsp;while (LCurrRec &lt; LRecSize) and (ClientThread.Socket.Connected) do begin<br> &nbsp; &nbsp; &nbsp; &nbsp;LTrueSize := ClientThread.Socket.ReceiveBuf(LRecBuff^, LTrueSize);<br> &nbsp; &nbsp; &nbsp; &nbsp;lUserbuff.PCurrRecvBUff^.Buff.WriteBuffer(LRecBuff^, LTrueSize);<br> &nbsp; &nbsp; &nbsp; &nbsp;inc(LCurrRec, LTrueSize);<br> &nbsp; &nbsp; &nbsp; &nbsp;inc(lUserbuff.CurrRecv, LTrueSize); {为了能让服务端检测到现在已经接收到的数据}<br> &nbsp; &nbsp; &nbsp; &nbsp;LTrueSize := Min(1024 * 8, LRecSize - LCurrRec);<br> &nbsp; &nbsp; &nbsp; &nbsp;{接满一个缓存后 使用下一个 如果下一个还在写 则等待写完}<br> &nbsp; &nbsp; &nbsp; &nbsp;while lUserbuff.PCurrRecvBUff^.Buff.Position &gt;= CMissonRecBuff do begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{把写满的缓存标记为可写入 让写入线程来写到文件内}<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lUserbuff.PCurrRecvBUff^.UseSize := lUserbuff.PCurrRecvBUff^.Buff.Position;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lUserbuff.PCurrRecvBUff^.IsCanWrite := 2;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{如果写入指针为空 则复值给它 }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if lUserbuff.PCurrWriteBuff = nil then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lUserbuff.PCurrWriteBuff := lUserbuff.PCurrRecvBUff;<br> &nbsp; &nbsp; &nbsp; &nbsp; {判断是否有可写的buff 有则继续接收 否则就检查等待}<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for i := low(lUserbuff.RecBuff) to High(lUserbuff.RecBuff) do begin // Iterate<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if lUserbuff.RecBuff.IsCanWrite = 1 then begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lUserbuff.PCurrRecvBUff := @lUserbuff.RecBuff;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Break;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end; //for<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{如果没有设置过缓冲则设置}<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if lUserbuff.PCurrRecvBUff^.Buff.Size &lt;&gt; CMissonRecBuff + 1024 * 8 then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SetBuff(lUserbuff.PCurrRecvBUff, CMissonRecBuff + 1024 * 8);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{如果磁盘还在写入则等待}<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if lUserbuff.PCurrRecvBUff^.Buff.Position &gt;= CMissonRecBuff then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sleep(10);<br> &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp;end; // while<br> &nbsp; &nbsp; &nbsp;Shower.AddShow('LCurrRec : %d LRecSize:%d ', [LCurrRec, LRecSize, BoolToStr(ClientThread.Socket.Connected)]);<br> &nbsp; &nbsp; &nbsp;if LCurrRec = LRecSize then begin<br> &nbsp; &nbsp; &nbsp; &nbsp;{正常结束的时候 要把正在接收的BUFF标记为可写入磁盘}<br> &nbsp; &nbsp; &nbsp; &nbsp;lUserbuff.PCurrRecvBUff^.UseSize := lUserbuff.PCurrRecvBUff^.Buff.Position;<br> &nbsp; &nbsp; &nbsp; &nbsp;lUserbuff.PCurrRecvBUff^.IsCanWrite := 2;<br> &nbsp; &nbsp; &nbsp; &nbsp;LOpter.FinishAnThread(Lbuff);<br> &nbsp; &nbsp; &nbsp;end<br> &nbsp; &nbsp; &nbsp;else<br> &nbsp; &nbsp; &nbsp; &nbsp;LOpter.State := Excepts;<br> &nbsp; &nbsp;except<br> &nbsp; &nbsp; &nbsp;on e: Exception do<br> &nbsp; &nbsp; &nbsp; &nbsp;Shower.AddShow('接收数据时异常原因 :%s 将结束此用户上传的所有相关线程', [e.Message]);<br> &nbsp; &nbsp;end;<br> &nbsp;finally<br> &nbsp; &nbsp;Dec(Tuser(ClientThread.fpSessionData).SubThreadCount);<br> &nbsp; &nbsp;ClientThread.fpSessionData := nil;<br> &nbsp; &nbsp;FreeMem(LRecBuff);<br> &nbsp; &nbsp;Shower.AddShow('接收数据结束 文件ID%D 起始:%d 到:%d ', [Lbuff.FileID, Lbuff.StartPos, Lbuff.EndPos]);<br> &nbsp; &nbsp;lUserbuff.IsFinish := True;<br> &nbsp;end;<br>end;
 
FileWrite减少调用可以减少资源调用<br>写文件是这样操作的:<br> &nbsp;FileWrite(Handle, S[1]{or P^}, Len);<br>但调用的频繁的话,CPU却很高,所以就有缓冲的说法:<br>var<br> &nbsp;WriteBuf: PChar; &nbsp; &nbsp;// 缓冲首地址<br> &nbsp;WriteBufLen, WriteBufVal: Integer; &nbsp;// buflen是缓冲开辟的长度,bufval是已使用长度<br><br> &nbsp;init:<br> &nbsp; WriteBufLen := 1024000; // 1M 看情况定,长度一般可以是:&gt; 你的数据包大小* 100<br> &nbsp; WriteBuf := allocMem(WriteBufLen);<br> &nbsp; WriteBufVal := 0;<br><br>write to buf:<br> &nbsp; procedure WriteToBuffer(AData: PChar; ALen: Integer); <br> &nbsp; begin<br> &nbsp; &nbsp; if (ALen + WriteBufVal &gt; WriteBufLen) or (ALen &lt;= 0) then<br> &nbsp; &nbsp; begin<br> &nbsp; &nbsp; &nbsp; &nbsp;FileWrite(Handle, WriteBuf^, AWriteBufVal); <br> &nbsp; &nbsp; &nbsp; &nbsp;AWriteBufVal := 0; <br> &nbsp; &nbsp; &nbsp; &nbsp;if ALen &lt;= 0 then Exit;<br> &nbsp; &nbsp; end;<br> &nbsp; &nbsp; Move(AData^, (WriteBuf + WriteBufVal)^, ALen);<br> &nbsp; &nbsp; Inc(WriteBufVal, ALen); &nbsp;<br> &nbsp; end;<br><br>free:<br> &nbsp;FreeMem(WriteBuf);<br><br>这样,有上面几个操作后,你只要调用WriteToBuffer即可达到写文件作用,如果线程需要退出,你再调用一次: WriteToBuffer(nil, 0);即可将已写入的缓冲写入文件。<br><br>这个就是减少写文件FileWrite的调用了。<br><br>FileOpen, FileClose也是减少损耗的,所以一般都是放在Exeucte中外循环:<br><br>procedure TmyThread.Execute;<br>begin<br> &nbsp;Handle := FileOpen(FileName, fmCreate or fmOpenReadWrite);<br> &nbsp;if Handle = INVALID_HANDLE_VALUE then <br> &nbsp; &nbsp; &nbsp;Error(...)<br> &nbsp;try<br> &nbsp; &nbsp;while not Terminated do &nbsp; <br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;...<br> &nbsp; &nbsp;end;<br> &nbsp;finally<br> &nbsp; &nbsp;CloseHandle(Handle);<br> &nbsp;end;<br>end;
 
分配,释放内存也是占资源的,你写个结构,直接转换,不要Move来来去去的<br><br>type<br> &nbsp;PData = ^TData;<br> &nbsp;TData = packed record<br> &nbsp; &nbsp;DataFlag: Cardinal;<br> &nbsp; &nbsp;MsgHdr: MyMessageHeader;<br> &nbsp; &nbsp;case Integer of<br> &nbsp; &nbsp; &nbsp;0: (<br> &nbsp; &nbsp; &nbsp; &nbsp;RecvHisData: MyBodyReceiveHisData;<br> &nbsp; &nbsp; &nbsp; &nbsp;RecvData: array [0..0] of Char;<br> &nbsp; &nbsp; &nbsp; &nbsp; );<br> &nbsp; &nbsp; &nbsp;1: (<br> &nbsp; &nbsp; &nbsp; &nbsp; // 其它类型<br> &nbsp; &nbsp; &nbsp; &nbsp; );<br> &nbsp;end;<br><br><br>procedure ProcReceiveHistoryThread.proBuffer(const ALength: Integer;<br> &nbsp;const ABuffer: PChar);<br>var<br> &nbsp;Data: PData;<br>begin<br> &nbsp;Data := Pointer(ABuffer);<br> &nbsp;if ALength &lt; SizeOf(TData) then Exit;<br> &nbsp;<br> &nbsp;if Data^.DataFlag = MY_MESSAGE_FLAG then Exit;<br> &nbsp;case Data^.MsgHdr.message_type of<br> &nbsp; &nbsp;204:<br> &nbsp; &nbsp; &nbsp;proSaveHistoryFile(Data^.RecvHisData, Data^.RecvData, Data^.RecvHisData.Length);<br> &nbsp;end; &nbsp;<br>end;
 
谢谢各位!<br>我先试试。
 
其实可以通过使用filemap的方法,应为他是一个相当底层的函数,速度自然不是问题,就是要注意一定要把要写的内容寄存到一定数量再调用这个函数,有点占内存,但是应该不成问题,还有就是看boradview系列的书中提到,如果是p3,p4处理器,就把寄存的要写的数量控制到16的倍数是有很好的效果的。再有就是不要像上面提到的那样随便挪动指针,否则会打破高速缓存上的内容的,最后只会适得其反,而如果有意调整指针使期数据对齐的话,速度可是成倍增长的!
 
硬件IO操作,还是改用CreateFile,WriteFile,ReadFile的异步方式吧。
 
while not terminated do<br>begin<br> &nbsp;if 有数据 then<br> &nbsp; &nbsp;处理<br> &nbsp;else<br> &nbsp; &nbsp;sleep(1);<br>end;<br>你看看你的代码有没有这么做?如果你按这个格式做,则CPU消耗一点点,不影响速度。
 
后退
顶部