I'm using named pipes for inter-procedural communication between C# and Delphi. C# uses the System.IO.Pipes
package, whereas Delphi makes use of Libby's pipes.pas
. Unfortunately, the communication is all but high-performance: Profiling showed me that the communication takes 72% of the whole runtime, the rest is used by calculations.
I was able to locate one problem that could take up resources: If I don't explicitly disconnect the sending client's connection in Delphi, C# doesn't receive any data at all.
Delphi (sending)
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# (receiving)
// 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();
Even though I guess that the reconnecting is expensive, I'm not entirely sure about it. One flow of data (roughly 1 / 11 kb) takes 130 (respectively 270ms for the 11kb) total (sending & receiving).
My question would be:
Is it necessary to force-disconnect the pipes to signalize that the client is done writing? As far as my observations go, this is only necessary when sending with libby's. Are there any other possible causes for the poor performance? Thanks in advance.
As an addition, here's the sending and receiving done vice versa:
C# (sending)
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 (receiving)
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