【发布时间】:2016-03-31 19:00:35
【问题描述】:
我正在使用 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();
}
我很难理解这种“简单”的代码更改如何对吞吐量产生如此大的影响。谁能帮我解释发生了什么?估计跟32feet的底层机制有关吧?
我来回更改了代码,结果每次都一样。传输的数据也是一样的。
我还直接从 Windows 连接到设备,然后在 Realterm 中打开 COM 端口以发送相同的数据。在这种情况下,我得到的吞吐量与使用 writer.Write(data.ToArray()) 相似。
我正在使用Microsoft Bluetooth Stack。
【问题讨论】:
-
这似乎很奇怪,不言自明。您一次将一个字节刷新到底层流,这显然比一次写入所有 250 个字节效率低。
-
看一下reference source,
Write(byte)调用底层流的Write(byte[], int, int)(NetworkStream不会覆盖WriteByte)用一个字节的缓冲区,而Write(byte[])调用相同的方法,但只是传递整个数组。 -
你的问题是“为什么调用一个方法比调用一次慢 250 倍?”那些方法调用不是免费的!迭代每个元素的 foreach 中的所有设备也不是。速度较慢的人做的附带工作是速度较快的人的 250 倍。
-
嗯,你们说的很明显。我实际上认为流有一个内部缓冲区,传入的数据只是附加到,然后在调用 Flush() 时这个缓冲区被刷新到底层机制。这样,在我的世界中,这两个替代方案的性能应该几乎相同(除了迭代和方法调用引入的额外开销,但这不应该弥补 96 毫秒)。
-
感谢@mikez 向我展示了参考来源。以前从未见过它,它让我意识到没有内部缓冲区可以按我假设的方式工作。如果您将您的评论作为答案,我会接受它,因为您为我指明了正确的方向并提供了足够的信息来帮助我解决我的问题。
标签: c# performance bluetooth binarywriter 32feet