1.背景
続き記事素人の言語C#の構造で-イーサネットパッケージのハートビートパケット、例えば、貧弱なパフォーマンスの構造を使用するだけでなく、理由を説明します。この記事では、ハートビートパケット網をカプセル化するクラスで詳細に長所と短所を説明し、結果が大幅に分析性能を改善しました。
2.ハートビートパケットカプセル化されたイーサネットクラスの長所と短所
2.1利点
- 次いで直接新しいバイト[]、直接インスタンスクラスであるバイトのアレイ、直接キャッシュコピー割り当てに渡された初期化メソッドやコンストラクタを書き込みます。
- あなたはボクシングとアンボクシングを必要としません。
- カテゴリは、参照型、画像構造をコピーせずに値が、底部層は、直接スマートポインタです。
- メモリ空間のセーブメモリの同じ部分にスマートポインタ。
- 私は簡単に、将来の拡張のためのオブジェクト指向、ドメイン指向の礎石であるクラスの便利なメソッドの多くを書くことができます。
2.2デメリット
- プレゼンスパイル、スタック幾分リード性能(迅速今PCの計算速度、実質的に無視できる)より。
- けれどもまた、管理GC、GCのリソースが、自動回復は、あなたは、IDisposableインターフェイスを実装するクラスのうち実行する必要は制御できない場合、クラスは手動でアクションをリリースしているに属しクラス。
実際のパフォーマンスクラスを使用する方法、我々が話すように、テストデータを使用して、我々は比較データと構造のテストのパフォーマンスの後ろに置かれます。
3.ネットワーク・ベースのハートビートパケットのカプセル化
ここでは、すべての名前が付けられます[]タイプ=新しいバイト[1]公共のバイトを含むバイト配列、となりました。それはバイト型タイプであれば、私は、時間のようなメモリリークなどの問題を引き起こす恐れがこの値型を解放する方法を知らないので。そして、各プロパティクラス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];
}
4.実装IDisposableインターフェイス
クラスを解放するためのイニシアチブを取るために、クラスの後に疲れ果て、私のリリースは、基本クラス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();
}
力試験における6.Dispose()メソッド
TY後に...最終的には廃棄()メソッドを実行してブロックし、プロパティの割り当てのクラスに行くヌルオブジェクトに割り当てられたエラーが成功したリリースを証明することであるならば、我々は、どうか、エラーを見てください。
finally
{
IDisposable disposable = tcpHeartPacketClass IDisposable;
if (disposable != null)
disposable.Dispose();
}
tcpHeartPacketClass.head[0] = 0x12;
私たちは解放されなければならないことは、対応するオブジェクト参照のインスタンスが存在しないことを意味変換し、次のエラー、。
7.比較試験性能
図に見ることができる、上記のクラスは、解析されたマイクロ秒であり、物品は、素人構造C# -ハートビートパケットカプセル化イーサネットの構成例アナリ数十マイクロ秒のレベル差はほぼ5 10倍のパフォーマンス。
したがって、このシナリオでは、ネットワーク構造をカプセル化するために、ハートビートパケットのクラスを使用するパッケージより合理的です。
要約8、C#、以下の二つの構造の主な効果:
- データ長は、体内で新しい16バイトの構成タイプ、サブタイプ及び構造は、スタック上の効率的な読み取りに対応するように設計され、意味そうでなければ、値型である必要があり、非常に短いではありません。
- C ++でのいくつかのライブラリからCとの互換性のために、
新しいアプリケーションを開発するために、私はC#で考える2以上の点を避けるため、完全に(だけの個人的見解に代わって)クラス構造に置き換えることができます。
免責事項:この記事はCC 4.0 BY-SAの著作権契約書に従って、ブロガーオリジナル記事です、複製、元のソースのリンクと、この文を添付してください。