Problemy z wydajnością nazwanych rur
Używam nazwanych potoków do komunikacji między procedurami między C # a Delphi. C # używaSystem.IO.Pipes
pakiet, podczas gdy Delphi korzysta zLibby's pipes.pas
. Niestety komunikacja jest bardzo wydajna: profilowanie pokazało, że komunikacja zajmuje 72% całego czasu pracy, reszta jest wykorzystywana przez obliczenia.
Udało mi się zlokalizować jeden problem, który mógłby zająć zasoby: jeśli nie rozłączę wyraźnie połączenia klienta wysyłającego w Delphi,C # nie otrzymuje żadnych danych.
FClient1.Write(msg[1], Length(msg));
FClient1.FlushPipeBuffers;
FClient1.WaitForReply(20);
FClient1.Disconnect; // disconnect to signalize C# that the writing is finished
FClient1.Connect; // connect again to prevent synchronization problems
C # (odbieranie)// Wait for a client to connect
stc.pipeServer.WaitForConnection();
while (reconnect_attempts < MAX_RECONNECT_ATTEMPTS) //
{
string tmp = sr.ReadLine();
// if result is empty, try again for <MAX_RECONNECT_ATTEMPTS> times
// so you can eliminate the chance that there's just a single empty request
while (tmp != null)// && result != tmp)
{
tmp = sr.ReadLine();
result += tmp;
}
// sleep, increment reconnect, write debugging...
}
stc.pipeServer.Close();
Chociaż myślę, że ponowne połączenie jest drogie, nie jestem do końca pewien. Jeden przepływ danych (w przybliżeniu 1/11 kb) zajmuje 130 (odpowiednio 270 ms dla 11 kb) ogółem (wysyłanie i odbieranie).
Moje pytanie byłoby:
Czy konieczne jest wymuszenie odłączenia rur, aby zasygnalizować, że klient skończył pisać? Jeśli chodzi o moje obserwacje,jest to konieczne tylko podczas wysyłania za pomocą libby's. Czy są jakieś inne możliwe przyczyny niskiej wydajności? Z góry dziękuję.
Dodatkowo, wysyłanie i odbieranie odbywa się na odwrót:
C # (wysyłanie) stc.pipeClient.Connect();
StreamWriter sw = new StreamWriter(stc.pipeClient);
//sw.AutoFlush = true;
sw.WriteLine(msg);
sw.Flush();
stc.pipeClient.WaitForPipeDrain(); // waits for the other end to read all bytes
// neither disconnect nor dispose
Delphi (odbieranie) SetLength(S, Stream.Size); Stream.Read(S[1], Length(S));
FPipeBuffer := FPipeBuffer + S; { TODO 2 : switch case ID }
// if the XML is complete, i.e. ends with the closing checksum
if (IsFullMessage()) then
begin
// end reading, set flag
FIsPipeReady := true;
end