Simplify the logic for NamedPipeStreamReader and fix handling of multiple sequential messages#343
Conversation
NamedPipeStreamReader and fix handling of multiple sequential messages
sanoursa
left a comment
There was a problem hiding this comment.
This version is much cleaner and easier to validate. If the perf is good, this is a better way to go, I think.
| private const byte TerminatorByte = 0x3; | ||
|
|
||
| private int bufferSize; | ||
| private byte[] buffer; |
There was a problem hiding this comment.
Mark this readonly now that we expect it to be a fixed 1-byte array forever
| { | ||
| int bytesRead = this.Read(); | ||
| if (bytesRead == 0) | ||
| byte readByte; |
There was a problem hiding this comment.
Nit: this sounds like the name of a delegate. Rename to currentByte?
| private int Read() | ||
| /// <param name="readByte">The byte read from the stream</param> | ||
| /// <returns>True if byte read, false if end of stream has been reached</returns> | ||
| private bool ReadByte(out byte readByte) |
There was a problem hiding this comment.
This method follows the Try pattern. Rename it to TryReadByte
| return this.stream.Read(this.buffer, 0, this.buffer.Length); | ||
| int numBytesRead = this.stream.Read(this.buffer, 0, 1); | ||
|
|
||
| if (numBytesRead > 0) |
There was a problem hiding this comment.
I think you can drop this condition and always execute line 73. The caller won't use the value if we return false, so there's no point in doing the check twice.
|
I'm just curious why we don't specify a size at the start of the message. That should make it simple to read and performant. |
I think that would be another fine option. I didn't go with it because it would require more changes to different components - we have native and managed components that communicate over the named pipe. The original problem was that the existing design did not handle messages with new line characters - performance was not a problem. The thought was that it would be better to just switch out the byte that represented the end of a message, rather than deeper changes to the protocol. |
246a228 to
2ba0774
Compare
The existing NamedPipe protocol expected that the sender of a message would wait for a response from the receiver before sending another message. It did not allow for multiple messages to be sent without the client responding. However, this is not a correct assumption, as there is at least 1 place where a component will send multiple messages without waiting for a response from the receiver (microsoft#333). This change updates the NamedPipeStreamReader to handle multiple messages sent sequentially, and simplifies the overall logic in the process. Tests are also included which exhibit this behavior.
2ba0774 to
df5ea19
Compare
|
Here is a table of data from the perf runs. A bit noisy, but I don't see any trends that indicate the simple approach introduces performance concerns. master branch
|
|
@jamill thanks for the perf numbers. In almost all cases, it actually appears that the simple solution is faster than the complex one. Definitely looks good to go. |
Update the
NamedPipeStreamReaderto read individual bytes from the underlying stream. This avoids complexity associated with reading a larger chunk of bytes and handling the different cases associated with that approach. This change also fixes handling of multiple sequential messages (#333)