2016-03-31 15 views
2

C# ve 32feet (sürüm 3.5) kullanıyorum, şu anda bellenimi yazdığım yerleşik bir cihaza bluetooth (SPP) üzerinden 250 baytlık bloklar göndermek için kullanıyorum.Neden BinaryWriter ile veri göndermek, foreach ve Write (Byte) kullanmak yerine Write (Byte []) kullanılarak çok daha hızlı mı?

Aşağıdaki kod ile bağlantımı kuruyorum:

var client = new BluetoothClient(); 
client.Encrypt = true; 
client.Connect(bluetoothAddress, ServiceClassId); 
NetworkStream stream = client.GetStream(); 
var writer = new BinaryWriter(stream); 

Ben çok düşük throughput ile biraz problem var ve her bloğun yaklaşık 100 ms aşağıdaki kodla transfer edilmesi aldı:

public void SendData(List<byte> data) 
{ 
    try 
    { 
     foreach (byte d in data) 
     { 
      writer.Write(d); 
     } 
     writer.Flush(); 
    } 
    catch (Exception) 
    { 
     // The connection was lost 
     ConnectionCleanup(); 
    } 
} 

Yukarıdaki kod bloğunu değiştirdikten sonra her bir blok 4 ms içinde iletilir.

try 
{ 
    writer.Write(data.ToArray()); 
    writer.Flush(); 
} 
catch (Exception) 
{ 
    // The connection was lost 
    ConnectionCleanup(); 
} 

Bu "basit" kod değişikliğinin çıktı üzerinde bu kadar büyük bir etkiye sahip olabileceğini anlamak için uğraşıyorum. Neler olduğunu açıklamama yardımcı olan var mı? Sanırım 32fe'nin altında yatan mekanizma ile bir ilgisi var mı?

Kodu ileri geri değiştirdim ve sonuç her seferinde aynı. Aktarılan veriler de aynıdır.

Ayrıca cihaza doğrudan Windows dan bağlandım ve daha sonra aynı verileri göndermek için Realterm'de COM portunu açtım. Bu durumda, writer.Write(data.ToArray())'u kullanarak benzer bir çıktı elde ediyorum.

Microsoft Bluetooth Stack kullanıyorum.

+1

Bu garip bir kendini açıklayıcı gibi görünüyor. Bir seferde her 250 kelimeyi yazmaktan daha az verimli olan temel akışa bir bayt atıyorsunuz. – Timeout

+0

[Referans kaynağı] 'na bir göz atın (http://referencesource.microsoft.com/#mscorlib/system/io/binarywriter.cs,cf806b417abe1a35),' Yaz (byte) 'temeldeki akışın 'Yazma (bayt [] ], int, int) '(NetworkStream' WriteByte 'işlevini geçersiz kılmaz) tek bir bayt tamponuyla, Write (byte []) 'da aynı yöntemi çağırır ancak tüm dizi boyunca geçer. –

+0

Sorunuz "bir yöntemi neden bir kez çağırmaktan 250 kez daha yavaş çağırıyor?" Bu yöntem çağrıları ücretsiz değil! Her öğenin üzerinde yineleyen foreach'daki tüm araçlar da değil. Daha yavaş olanı 250 kat daha rastlantısal bir işi daha hızlı yapıyor. –

cevap

2

BinaryWriter için reference source bir göz atın, Write(byte), temel akış en WriteByte(byte) çağırır Write(byte[]) aramalar Write(byte[], int, int) iken. ayrıca baktığımızda base implementation kullanılır böylece NetworkStream sanal yöntem writeByte geçersiz kılmaz görüyoruz:

// 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); 
} 

Ayrıca NetworkStream hiçbir dahili tampon vardır, sadece altta yatan Socket için Yaz çağrıları geçirir. İlk durumda 250 ağ görüşmesi yapıyorsunuz, ikincisinde ise 1, bu nedenle performans farkının nedeni açık olmalı.