调优从NetworkStream读取小数据的缓冲区长度
本文关键字:缓冲区 数据 小数 NetworkStream 读取 | 更新日期: 2023-09-27 18:15:38
如何在从TcpClient/networkstream读取小数据时微调bufferSize ?如果bufferSize很大,比如1024,4096,则Read/BeginRead块。如果我将bufferSize设置为16,32,它可以不阻塞地工作。
- 设置bufferSize为1保证不会有任何块吗?性能影响会非常糟糕吗?
-
看起来像将ReadTimeout设置为1000,2000这样的值对阻塞没有影响。还有其他方法可以阻塞吗是短的吗?(NoDelay = true不起作用)
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); }
它看起来像设置ReadTimeout设置为1000,2000对阻塞没有影响。
Msdn说,当使用async BeginRead
方法时,ReadTimeout没有影响。
设置bufferSize为1保证不会有任何块吗?
没有,当然没有。当没有一个字节通过连接发送时,无论缓冲区大小如何,Read调用都会阻塞。
性能影响会很糟糕吗?
我猜你说的是1字节缓冲区。这取决于您接收的数据的数量和频率以及您在EndRead
上执行的代码。当处理具有高带宽的流时,影响可能很大。当你接收数据时,你必须试着观察你的cpu。
我不太确定你想分别实现什么,你对阻塞的担忧是什么。
当你用1024字节的缓冲区启动Receive(或Networkstream.Read)时,你在套接字上收到10字节,Read调用将在短暂的延迟后返回这10字节,但不会阻塞,直到整个缓冲区被填满。
还有其他方法可以使阻塞缩短吗?
短是什么意思?正如我所说,即使有很大的缓冲区,当接收到少量数据时,Read也不会无休止地阻塞。
(NoDelay = true不起作用)
这是一个完全不同的故事,但在您的发送方将其设置为true
可能会很有趣(如果您也可以控制它)。
当设置为false(默认)时,它会将发送的小数据块合并为大数据块,以减少一个tcp数据包(40字节报头)的开销。
编辑
我是说NetworkStream。如果没有数据,BeginRead将立即返回。
使用stream.DataAvailable
怎么样?当没有数据时,它应该返回false。
此外,当使用异步模式时,它不是预期的行为,调用将阻塞,直到有事情要做?否则,您将在繁忙循环中获得活动轮询。
当缓冲区很大时,它有时会等待60秒返回(当它没有完全填充或填充到一定数量时)
嗯,真不敢相信。你通过信道发送什么样的数据?每分钟1字节?每秒1000字节?