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