Buffer length for reading small data from NetworkStream

How to properly configure bufferSize when reading small data from TcpClient / NetworkStrem? If bufferSize is as large as 1024, 4096 Read / BeginRead blocks. If I set bufferSize to 16, 32, it will work without blocking.

  • Does bufferSize set the value to 1 that there will be no blocks? Will the performance impact be very bad?
  • It seems that setting ReadTimeout to values ​​such as 1000, 2000 has no effect on locking. Is there any other way to make the lock be short? (NoDelay = true does not work)

    public static IObservable<byte[]> AsyncReadChunk(this Stream stream, int bufferSize) { var buffer = new byte[bufferSize]; return Observable.FromAsyncPattern<byte[], int, int, int>(stream.BeginRead, stream.EndRead)(buffer, 0, bufferSize) .Select(cbRead => { var dataChunk = new byte[cbRead]; Buffer.BlockCopy(buffer, 0, dataChunk, 0, cbRead); return dataChunk; }); } public static IObservable<byte[]> AsyncRead(this NetworkStream stream, int bufferSize) { return Observable.Defer(() => stream.DataAvailable ? AsyncReadChunk(stream, bufferSize) : Observable.Return(new byte[0])) .Repeat() .TakeWhile((dataChunk, index) => dataChunk.Length > 0); } 
+4
source share
1 answer

It seems that ReadTimeout up to values ​​like 1000, 2000 does not affect the lock.

Msdn says ReadTimeout has no effect when using the async BeginRead method.

Is bufferSize set to 1 so that there are no blocks?

No, for no reason. If no bytes are sent over the connection, the Read call will block regardless of buffering.

Will the performance impact be very bad?

I think you are talking about a 1-byte buffer. It depends on the amount and frequency of data you receive and on what code you execute on EndRead . When processing a stream with high throughput, the impact can be large. You should try and see your processor when receiving data.

I'm not quite sure what you want to achieve, respectively, that your concern is about blocking.

When you start Receive (or Networkstream.Read) with a buffer, say 1024 bytes, and you get 10 bytes in the socket, a Read call will return this 10 bytes after a short delay, but will not be blocked until the entire buffer is full.

Is there any other way to make the lock short?

What do you mean with a short. As I said, even with a large buffer, Read will not block indefinitely when receiving small amounts of data.

(NoDelay = true does not work)

This is a completely different story , but it may be interesting to set it to true on the side of your senders (if you control this too).

If set to false (the default), it will combine small data shunts sent to larger ones to reduce the overhead of a single tcp packet (40-byte header).

EDIT

I mean NetworkStream.BeginRead to return immediately if there is no data.

How about using stream.DataAvailable ? It should return false when there is no data.

Also, when using the async pattern, is not the expected behavior that calls will block until it does something? Otherwise, you will receive an active survey in the employment cycle.

When the buffer is large, it sometimes waits 60 seconds to return (when it is not full or full to a certain value)

Nm, I can’t believe it. What data do you send on the channel? 1 byte every minute? 1000 bytes per second?

+2
source

Source: https://habr.com/ru/post/1383070/


All Articles