为什么使用 Write(Byte[]) 而不是使用 foreach 和 Write(Byte) 用 BinaryWriter 发送数据要快得多?
Why is sending data with BinaryWriter so much faster using Write(Byte[]) instead of using foreach and Write(Byte)?
我正在使用 C#
和 32feet
(版本 3.5)通过蓝牙 (SPP) 将 250 字节的块发送到我当前正在为其编写固件的嵌入式设备。
我正在使用以下代码建立连接:
var client = new BluetoothClient();
client.Encrypt = true;
client.Connect(bluetoothAddress, ServiceClassId);
NetworkStream stream = client.GetStream();
var writer = new BinaryWriter(stream);
我遇到了一些吞吐量非常低的问题,使用以下代码传输每个块大约需要 100 毫秒:
public void SendData(List<byte> data)
{
try
{
foreach (byte d in data)
{
writer.Write(d);
}
writer.Flush();
}
catch (Exception)
{
// The connection was lost
ConnectionCleanup();
}
}
将上面的代码块更改为下面的代码后,每个块在 4 毫秒内传输。
try
{
writer.Write(data.ToArray());
writer.Flush();
}
catch (Exception)
{
// The connection was lost
ConnectionCleanup();
}
我很难理解此 "simple" 代码更改为何会对吞吐量产生如此大的影响。谁能帮我解释一下这是怎么回事?估计跟32feet的底层机制有关系吧?
我来回更改代码,每次结果都一样。传输的数据也是一样
我还直接从 Windows 连接到设备,然后在 Realterm 中打开 COM 端口以发送相同的数据。在这种情况下,我获得与使用 writer.Write(data.ToArray())
.
类似的吞吐量
我正在使用 Microsoft Bluetooth Stack
。
看看reference source for BinaryWriter
, Write(byte)
calls the underlying stream's WriteByte(byte)
, while Write(byte[])
calls Write(byte[], int, int)
. Looking further, we see that NetworkStream does not override the virtual method WriteByte so the base implementation的用法:
// Writes one byte from the stream by calling Write(byte[], int, int).
// This implementation does not perform well because it allocates a new
// byte[] each time you call it, and should be overridden by any
// subclass that maintains an internal buffer. Then, it can help perf
// significantly for people who are writing one byte at a time.
public virtual void WriteByte(byte value)
{
byte[] oneByteArray = new byte[1];
oneByteArray[0] = value;
Write(oneByteArray, 0, 1);
}
此外,NetworkStream
没有内部缓冲区,它只是将写入调用传递给底层 Socket
。您在第一种情况下进行了 250 次网络调用,在第二种情况下进行了 1 次,因此性能差异的原因应该很明显。
我正在使用 C#
和 32feet
(版本 3.5)通过蓝牙 (SPP) 将 250 字节的块发送到我当前正在为其编写固件的嵌入式设备。
我正在使用以下代码建立连接:
var client = new BluetoothClient();
client.Encrypt = true;
client.Connect(bluetoothAddress, ServiceClassId);
NetworkStream stream = client.GetStream();
var writer = new BinaryWriter(stream);
我遇到了一些吞吐量非常低的问题,使用以下代码传输每个块大约需要 100 毫秒:
public void SendData(List<byte> data)
{
try
{
foreach (byte d in data)
{
writer.Write(d);
}
writer.Flush();
}
catch (Exception)
{
// The connection was lost
ConnectionCleanup();
}
}
将上面的代码块更改为下面的代码后,每个块在 4 毫秒内传输。
try
{
writer.Write(data.ToArray());
writer.Flush();
}
catch (Exception)
{
// The connection was lost
ConnectionCleanup();
}
我很难理解此 "simple" 代码更改为何会对吞吐量产生如此大的影响。谁能帮我解释一下这是怎么回事?估计跟32feet的底层机制有关系吧?
我来回更改代码,每次结果都一样。传输的数据也是一样
我还直接从 Windows 连接到设备,然后在 Realterm 中打开 COM 端口以发送相同的数据。在这种情况下,我获得与使用 writer.Write(data.ToArray())
.
我正在使用 Microsoft Bluetooth Stack
。
看看reference source for BinaryWriter
, Write(byte)
calls the underlying stream's WriteByte(byte)
, while Write(byte[])
calls Write(byte[], int, int)
. Looking further, we see that NetworkStream does not override the virtual method WriteByte so the base implementation的用法:
// Writes one byte from the stream by calling Write(byte[], int, int).
// This implementation does not perform well because it allocates a new
// byte[] each time you call it, and should be overridden by any
// subclass that maintains an internal buffer. Then, it can help perf
// significantly for people who are writing one byte at a time.
public virtual void WriteByte(byte value)
{
byte[] oneByteArray = new byte[1];
oneByteArray[0] = value;
Write(oneByteArray, 0, 1);
}
此外,NetworkStream
没有内部缓冲区,它只是将写入调用传递给底层 Socket
。您在第一种情况下进行了 250 次网络调用,在第二种情况下进行了 1 次,因此性能差异的原因应该很明显。