接上篇文章深刻淺出C#結構體——封裝以太網心跳包的結構爲例,使用結構體性能不佳,並且也說明了緣由。本篇文章詳細描述了以類來封裝網絡心跳包的優缺點,結果大大提高了解析性能。html
使用類的實際性能怎樣,咱們用測試數聽說話,後面會放上與結構體測試的性能對比數據。數組
這裏所有都命名成了字節數組,包括 public byte[] type=new byte[1];由於若是是byte type類型,我不知道如何去釋放這一值類型,怕到時候引發內存泄露等問題。而後在構造函數裏面將緩存buf拷貝到了類的各個屬性中,就是這麼簡單。緩存
public class TcpHeartPacketClass: BaseDisposable { private bool _disposed; //表示是否已經被回收 public TcpHeartPacketClass(byte[] buf) { Buffer.BlockCopy(buf, 0, head, 0, 4); type[0] = buf[4]; Buffer.BlockCopy(buf, 4, length, 0, 2); Buffer.BlockCopy(buf, 6, Mac, 0, 6); Buffer.BlockCopy(buf, 12, data, 0, 104); Buffer.BlockCopy(buf, 116, tail, 0, 4); } protected override void Dispose(bool disposing) { if (!_disposed) //若是尚未被回收 { if (disposing) //若是須要回收一些託管資源 { //TODO:回收託管資源,調用IDisposable的Dispose()方法就能夠 } //TODO:回收非託管資源,把之設置爲null,等待CLR調用析構函數的時候回收 head = null; type = null; length = null; Mac = null; data = null; tail = null; _disposed = true; } base.Dispose(disposing);//再調用父類的垃圾回收邏輯 } public byte[] head=new byte[4]; public byte[] type=new byte[1]; public byte[] length = new byte[2]; public byte[] Mac = new byte[6]; public byte[] data = new byte[104];//數據體 public byte[] tail = new byte[4]; }
用完類以後,爲了主動去釋放類,我封裝了一個釋放基類BaseDisposable。詳見代碼註釋,有不明白的地方能夠在評論區提問,我會詳細做答。網絡
public class BaseDisposable : IDisposable { ~BaseDisposable() { //垃圾回收器將調用該方法,所以參數須要爲false。 Dispose(false); } /// <summary> /// 是否已經調用了 Dispose(bool disposing)方法。 /// 應該定義成 private 的,這樣可使基類和子類互不影響。 /// </summary> private bool disposed = false; /// <summary> /// 全部回收工做都由該方法完成。 /// 子類應重寫(override)該方法。 /// </summary> /// <param name="disposing"></param> protected virtual void Dispose(bool disposing) { // 避免重複調用 Dispose 。 if (!disposed) return; // 適應多線程環境,避免產生線程錯誤。 lock (this) { if (disposing) { // ------------------------------------------------ // 在此處寫釋放託管資源的代碼 // (1) 有 Dispose() 方法的,調用其 Dispose() 方法。 // (2) 沒有 Dispose() 方法的,將其設爲 null。 // 例如: // xxDataTable.Dispose(); // xxDataAdapter.Dispose(); // xxString = null; // ------------------------------------------------ } // ------------------------------------------------ // 在此處寫釋放非託管資源 // 例如: // 文件句柄等 // ------------------------------------------------ disposed = true; } } /// <summary> /// 該方法由程序調用,在調用該方法以後對象將被終結。 /// 該方法定義在IDisposable接口中。 /// </summary> public void Dispose() { //由於是由程序調用該方法的,所以參數爲true。 Dispose(true); //由於咱們不但願垃圾回收器再次終結對象,所以須要從終結列表中去除該對象。 GC.SuppressFinalize(this); } /// <summary> /// 調用 Dispose() 方法,回收資源。 /// </summary> public void Close() { Dispose(); } }
DateTime packetClassStart = DateTime.Now; TcpHeartPacketClass tcpHeartPacketClass = neTcpHeartPacketClass(ReceviveBuff); DateTime packetClassEnd = DateTime.Now; TimeSpan toClassTs = packetClassEnd.Subtra(packetClassStart); try { tcpHeartPacketClass.head[0] = 0x11; LoggerHelper.Info("類中的包頭:" + BitConverteToString(tcpHeartPacketClass.head)); Console.WriteLine("類中的包頭:{0}", BitConverteToString(tcpHeartPacketClass.head)); LoggerHelper.Info("類中的包類型:" tcpHeartPacketClass.type.ToString()); Console.WriteLine("類中的包類型:{0}"tcpHeartPacketClass.type.ToString()); LoggerHelper.Info("類中的包長度:" + BitConverteToString(tcpHeartPacketClass.length)); Console.WriteLine("類中的包長度:{0}", BitConverteToString(tcpHeartPacketClass.length)); LoggerHelper.Info("類中的MAC地址:" + BitConverteToString(tcpHeartPacketClass.Mac)); Console.WriteLine("類中的MAC地址:{0}", BitConverteToString(tcpHeartPacketClass.Mac)); LoggerHelper.Info("類中的註冊包內容:" + BitConverteToString(tcpHeartPacketClass.data)); Console.WriteLine("類中的註冊包內容:{0}"BitConverter.ToString(tcpHeartPacketClass.data)); LoggerHelper.Info("類中的包尾:" + BitConverteToString(tcpHeartPacketClass.tail)); Console.WriteLine("類中的包尾:{0}", BitConverteToString(tcpHeartPacketClass.tail)); Console.WriteLine("字節數組類中分割總共花費{0}ms\n"toClassTs.TotalMilliseconds); } finally { IDisposable disposable = tcpHeartPacketClass as IDisposable; if (disposable != null) disposable.Dispose(); }
在ty...finally塊執行完Dispose()方法以後,再去給類的某個屬性賦值,咱們看是否報錯,若是報錯賦值給空對象則證實釋放成功。多線程
finally { IDisposable disposable = tcpHeartPacketClass IDisposable; if (disposable != null) disposable.Dispose(); } tcpHeartPacketClass.head[0] = 0x12;
以下報錯,翻譯過來意思就是對象引用沒有對應的實例,也就是被咱們給釋放掉了。tcp
經過上圖能夠看到,上面的類解析的是微秒級別的,而文章深刻淺出C#結構體——封裝以太網心跳包的結構爲例解析的是幾十微秒級別的,差了差很少5到10倍的性能。ide
因而可知,在這種應用場景下,使用類來封裝網絡心跳包比結構體封裝更合理。函數