perf(scripting): #789 give the Windows worker pipe a 1 MiB buffer quota each way
With a zero quota an overlapped write stays pending until the peer has read the bytes, so the new blocking writer waited out a peer wake-up per frame (windev closed loop 54k -> 26k evals/s). With a quota the write completes once buffered. Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk
This commit is contained in:
@@ -50,11 +50,20 @@ internal static class WorkerPipeSecurity
|
||||
return security;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The pipe's buffer quota in each direction (lmxopcua#789). With a quota of 0 an overlapped write stays pending
|
||||
/// until the peer has READ the bytes, so a blocking writer (<see cref="ZB.MOM.WW.OtOpcUa.Core.Scripting.Protocol.WindowsBlockingPipeStream"/>)
|
||||
/// would wait out a full peer wake-up per frame — measured on windev as half the closed-loop throughput. With a
|
||||
/// quota a write completes as soon as the bytes are buffered; a peer that stops reading still fills it and blocks
|
||||
/// the writer, which the heartbeat monitor ends.
|
||||
/// </summary>
|
||||
internal const int BufferBytes = 1024 * 1024;
|
||||
|
||||
/// <summary>Creates the single-instance server end of a worker pipe with <paramref name="security"/>.</summary>
|
||||
/// <param name="pipeName">The random pipe name.</param>
|
||||
/// <param name="security">The ACL (<see cref="ForCurrentHost"/>).</param>
|
||||
/// <returns>The server stream.</returns>
|
||||
public static NamedPipeServerStream CreateServer(string pipeName, PipeSecurity security)
|
||||
=> NamedPipeServerStreamAcl.Create(pipeName, PipeDirection.InOut, maxNumberOfServerInstances: 1,
|
||||
PipeTransmissionMode.Byte, PipeOptions.Asynchronous, inBufferSize: 0, outBufferSize: 0, security);
|
||||
PipeTransmissionMode.Byte, PipeOptions.Asynchronous, inBufferSize: BufferBytes, outBufferSize: BufferBytes, security);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user