RO 收发数据的过程优化 性能提升可观!!

 

RO  SDK 版本: 6.0.45.821 代码在 uROSynapseSCHelpers.pas 单元

优化原理如下:

      如果我们认真查看接收函数ReadStream, 发送函数IntSendData时,我们可以发现RO SDK都是

      先把要发送或接收的数据存进临时内存 Buf , 这种做法数据被无谓多COPY了一次,

如果我们能跳过这一步,在大数量并发的情况下将获得可观的性能提升.

      话不多说, 代码直接贴出来,  这些代码都是经过项目实际测试过的, 大家可以直接COPY修改掉RO SDK控件的源代码, 重新编译你的程序即可!!

 

function TROSynSuperChannelWorker.ReadStream(aDest: TStream; aLen: Integer): Boolean;
var
  Buf: array[0 .. 4096-1] of byte;
  lRes: Integer;

  // Added by hanhuotu 2010-10-14 16:27:31
  DataMemory: LongInt;
  DataPosition: int64;
begin
  aDest.Position := 0;
  if aDest is TCustomMemoryStream then   // Modified by hanhuotu 2010-10-14 15:51:15
  begin
    aDest.Size := aLen;
    DataMemory := Longint(TCustomMemoryStream(aDest).Memory);
    DataPosition := TCustomMemoryStream(aDest).Position;
    while aLen > 0 do begin
      lRes := aLen;
      if lRes > sizeof(buf) then lRes := Sizeof(Buf);

      lRes := fConnection.RecvBufferEx(Pointer(DataMemory + DataPosition),
        lRes, fPingFrequency * 10000);     //效率大大的提高

      inc(DataPosition, lRes);

      aLen := aLen - lRes;
      if lRes = 0 then
      begin
        Result := false;
        exit;
      end;

      fLastData := now;
    end;
  end
  else begin
    aDest.Size := 0;
    while aLen > 0 do
    begin
      lRes := aLen;
      if lRes > sizeof(buf) then lRes := Sizeof(Buf);

      // Modified by hanhuotu 2010-03-29 12:18:30
      //lRes := fConnection.RecvBufferEx(@Buf[0], lRes, fPingFrequency * 1000);
      lRes := fConnection.RecvBufferEx(@Buf[0], lRes, fPingFrequency * 10000);
      // End by hanhuotu 2010-03-29 12:18:41

      aLen := aLen - lRes;
      if lRes = 0 then begin Result := false; exit; end;
      aDest.Write(Buf, lRes);
      fLastData := now;
    end;
  end;

  Result := true;
end;

 

function TROSynSuperChannelWorker.IntSendData(Id: Integer; aData: TStream): IROSynapsePackageAck;
var
  //Buffer: array[0.. 2047] of byte;
  Buffer: array[0.. 1447] of byte;
  Len: Integer;

  // Added by hanhuotu 2010-10-14 16:27:31
  DataLen, BufferLen: Integer;
  DataMemory: LongInt;
  DataPosition: int64;
  aTime: cardinal;
begin
  fLastData := Now;
  Result := TROSynPackageAck.Create(Self, Id);

  // Added by hanhuotu 2010-03-29 8:57:14
  if Result.Event <> nil then
    fWaitingAckList.Add(Result);

  // End by hanhuotu 2010-03-29 8:58:36
 
  Buffer[0] := ScCmdPackage;
  Move(Id, Buffer[1], 4);
  Len := aData.Size;
  Move(Len, Buffer[5], 4);

  DataLen := Len;  // Added by hanhuotu 2010-10-14 16:10:43
  BufferLen := sizeof(Buffer);

  aData.Seek(0, soFromBeginning);

  fInternalWriteLock.Acquire;
  try
    Len := aData.Read(Buffer[9], sizeof(Buffer) - 9);
    //aTime := GetTickCount;
    fConnection.SendBuffer(@Buffer, Len + 9);
    //inc(ByteNum, Len + 9);
    //inc(TimeNum, GetTickCount - aTime);
    if Len > 0 then begin
      if aData is TCustomMemoryStream then   // Added by hanhuotu 2010-10-14 16:35:27
      begin
        DataMemory := Longint(TCustomMemoryStream(aData).Memory);  //效率大大的提高
        DataPosition := aData.Position;
        while DataPosition < DataLen do
        begin
          Len := DataLen - DataPosition;
          if Len > BufferLen then Len := BufferLen;

          //aTime := GetTickCount;
          fConnection.SendBuffer(Pointer(DataMemory + DataPosition), Len);
          //inc(ByteNum, Len);
          //inc(TimeNum, GetTickCount - aTime);

          inc(DataPosition, Len);

          fLastData := Now;
        end;
      end
      else begin
        repeat
          Len := aData.Read(Buffer[0], Sizeof(Buffer));
          fConnection.SendBuffer(@Buffer[0], Len);
          fLastData := Now;
        until Len = 0;
      end; 
    end;
  finally
    fInternalWriteLock.Release;
  end;
end;

 

      其实RO SDK 最大的性能瓶颈是在RO 为每个客户端连接都开了一个线程,

这样当客户端数量很多比如有500个情况, RO的性能就显得差很多了,

这时候就需要终极武器IOCP出场了, RO  SDK 并没有提供这样的控件,

我花了近一个月时间刚开发完成,  性能强悍!!  

 

      有需要可以和我联系 QQ:  9717005

 

 

 

posted @ 2010-12-05 19:41  doorkey  阅读(1982)  评论(1编辑  收藏  举报