gpt4 book ai didi

performance - Indy10,400ms 简单的 TCP/IP 请求和响应

转载 作者:可可西里 更新时间:2023-11-01 02:57:06 26 4
gpt4 key购买 nike

我不明白为什么一个简单的请求和响应需要 400 毫秒才能完成。它只需要不到 1 毫秒就可以在本地主机上完成(环回)。当我从我的虚拟机向我的主要开发机器发出请求时,需要 400 毫秒才能完成。最多需要 40 毫秒。这是一个 HTTP 请求最多需要多少,所以 TCP 应该更快。这是客户端和服务器的代码。我只是看不出我在哪里浪费时间。如果您需要更多信息,我可以介绍。

代码与 Indy 9 和 10 兼容,这就是 IFDEF-s 的原因。而且连接已经建立,没有连接部分需要 400 毫秒,只有数据发送和响应。

function TIMCClient.ExecuteConnectedRequest(const Request: IMessageData): IMessageData;
var
DataLength: Int64;
FullDataSize: Int64;
IDAsBytes: TIdBytes;
IDAsString: ustring;
begin
Result := AcquireIMCData;
FAnswerValid := False;

with FTCPClient{$IFNDEF Indy9}.IOHandler{$ENDIF} do
begin
Request.Data.Storage.Seek(0, soFromBeginning);
DataLength := Length(Request.ID) * SizeOf(uchar);
FullDataSize := DataLength + Request.Data.Storage.Size + 2 * SizeOf(Int64);

SetLength(IDAsBytes, DataLength);
Move(Request.ID[1], IDAsBytes[0], DataLength);

// write data
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(FullDataSize);
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(DataLength);
{$IFDEF Indy9}WriteBuffer{$ELSE}Write{$ENDIF}(IDAsBytes{$IFDEF Indy9}[0]{$ENDIF}, DataLength);
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(Request.Data.Storage.Size);
{$IFDEF Indy9}WriteStream{$ELSE}Write{$ENDIF}(Request.Data.Storage);

// set the read timeout
ReadTimeout := FExecuteTimeout;
FullDataSize := ReadInt(FTCPClient);

// read the message ID
SetLength(IDAsBytes, 0);
DataLength := ReadInt(FTCPClient);
ReadBuff(FTCPClient, DataLength, IDAsBytes);

if DataLength > 0 then
begin
SetLength(IDAsString, DataLength div SizeOf(uchar));
Move(IDAsBytes[0], IDAsString[1], DataLength);
Result.ID := IDAsString;
end;

// read the message data
DataLength := ReadInt(FTCPClient);
ReadStream(Result.Data.Storage, DataLength, False);
Result.Data.Storage.Seek(0, soFromBeginning);

// we were succesfull
FAnswerValid := True;
end;
end;

服务器端:

procedure TIMCServer.OnServerExecute(AContext: TIMCContext);
var
Request: IMessageData;
Response: IMessageData;
DataLength: Int64;
FullDataSize: Int64;
IDAsBytes: TIdBytes;
IDAsString: ustring;
begin
with AContext.Connection{$IFNDEF Indy9}.IOHandler{$ENDIF} do
begin
ReadTimeout := FExecuteTimeout;
//read the data length of the comming response
FullDataSize := ReadInt(AContext.Connection);

// Acquire the data objects
Request := AcquireIMCData;
Response := AcquireIMCData;

// read the message ID
DataLength := ReadInt(AContext.Connection);
ReadBuff(AContext.Connection, DataLength, IDAsBytes);

if DataLength > 0 then
begin
SetLength(IDAsString, DataLength div SizeOf(uchar));
Move(IDAsBytes[0], IDAsString[1], DataLength);
Request.ID := IDAsString;
end;

// read the message data
DataLength := ReadInt(AContext.Connection);
ReadStream(Request.Data.Storage, DataLength, False);

Request.Data.Storage.Seek(0, soFromBeginning);
try
// execute the actual request handler
FOnExecuteRequest(Request, Response);
finally
// write the data stream to TCP
Response.Data.Storage.Seek(0, soFromBeginning);
DataLength := Length(Response.ID) * SizeOf(uchar);
FullDataSize := DataLength + Response.Data.Storage.Size + 2 * SizeOf(Int64);

// write ID as binary data
SetLength(IDAsBytes, DataLength);
Move(Response.ID[1], IDAsBytes[0], DataLength);

// write data
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(FullDataSize);
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(DataLength);
{$IFDEF Indy9}WriteBuffer{$ELSE}Write{$ENDIF}(IDAsBytes{$IFDEF Indy9}[0]{$ENDIF}, DataLength);
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(Response.Data.Storage.Size);
{$IFDEF Indy9}WriteStream{$ELSE}Write{$ENDIF}(Response.Data.Storage);
end;
end;

我的代码的一位用户报告了同样缓慢的通信。他还从虚拟机到物理机进行了测试。

更新:

以下代码在相同两台机器之间的执行时间为 2-3 毫秒。它的 Indy10,尽可能小的情况。

procedure TForm2.Button1Click(Sender: TObject);
var
MyVar: Int64;
begin
TCPClient.Host := Edit1.Text;
TCPClient.Port := StrToInt(Edit2.Text);
TCPClient.Connect;
try
stopwatch := TStopWatch.StartNew;
MyVar := 10;
TCPClient.IOHandler.Write(MyVar);
TCPClient.IOHandler.ReadInt64;
stopwatch.Stop;
Caption := IntToStr(stopwatch.ElapsedMilliseconds) + ' ms';
finally
TCPClient.Disconnect;
end;
end;

procedure TForm2.TCPServerExecute(AContext: TIdContext);
var
MyVar: Int64;
begin
if AContext.Connection.IOHandler.InputBuffer.Size > 0 then
begin
MyVar := 10;
AContext.Connection.IOHandler.ReadInt64;
AContext.Connection.IOHandler.Write(MyVar);
end;

结束;

最佳答案

问题解决了。当您找出要做什么以及问题出在哪里时,这很容易。 Indy 根本没有立即发送我的数据。我必须添加

OpenWriteBuffer
CloseWriteBuffer

调用让 Indy 在我需要时发送数据。对内部运作的简单误解会带来很多麻烦。也许这会节省一些时间。

当缓冲区关闭时,立即发送数据!

关于performance - Indy10,400ms 简单的 TCP/IP 请求和响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15859891/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com