簡體   English   中英

如何進一步優化(首先是速度,然后是內存)

[英]How to optimize this further (speed first, then memory)

我有這個小的代碼,需要一個對象並將其轉換為byte []。 使用C#4.0。 我可以進一步優化速度和內存使用嗎? 即使很小的變化也將是巨大的-每秒調用數千次以上。

    public static byte[] ObjectToByteArray(object obj)
    {
        if (obj == null)
            return null;
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();

        using (ms)
        {
            bf.Serialize(ms, obj);  
        }

        return ms.ToArray();
    }

如果您想進一步優化它,那么您首先需要知道的是您目前在哪里花費最多的時間。 您是否通過探查器運行此程序? 結果如何?

我還會問自己“優化此功能將為用戶帶來什么具體好處?”。 換句話說,我是否在優化它,是因為作為一名工程師,我想完善代碼,還是因為它將為交付解決方案的人員帶來真正的好處?

我懷疑您花了大部分時間執行實際的序列化,更改為其他序列化器可能會產生最大的收益。 有關替代的,更快的序列化器,請參見以下問題:

.NET中快速緊湊的對象序列化

問題在於BinaryFormatter使用反射來讀取對象的字段。 假設您有一個包含1個字段的簡單類:

[Serializable]
public class Test
{
    public int A;
}

如果使用BinaryFormatter序列化一個數組,它將對Test的每個實例執行類似的操作:

int val = (int)typeof(Test).GetField("A").GetValue(obj);
var bytes = BitConverter.GetBytes(val);
stream.Write(bytes, 0, bytes.Length);

調用GetField()將花費大量時間。 您可以使用3種方法來顯着提高速度:

  1. 手動序列化所有內容。 類似於以下代碼:

     void SimpleSerialize(Stream stream, Test[] arr) { foreach (var obj in arr) { var bytes = BitConverter.GetBytes(obj.A); stream.Write(bytes, 0, bytes.Length); } } 
  2. 使用Reflection.Emit功能即時生成自定義序列化類。 這是更通用且“干凈”的方法,但需要付出很多努力。

  3. 如果您滿意,請使用一些適合您需要的第三方串行器

確實沒有什么可以改進此代碼的。 如果要處理簡單的對象,則可以通過用BinaryWriter替換BinaryFormatter並手動序列化每個字段/屬性來改進此代碼,這將是最快的序列化。 但這是一個極端的措施,只有在實驗確定該代碼在某種程度上成為應用程序的瓶頸時,才應采取此措施。 否則,您可能會浪費時間進行微優化。

定義一個ThreadStatic byte[]作為實例字段,並將其用作緩存。 將您的內存流包裝在此緩存對象周圍。 當您按代碼編寫使用MemoryStream ,將執行大量的分配,重新分配和數組復制步驟,因為MemoryStream可以調整大小。 還需要考慮垃圾收集的成本。

可能的是,盡管我不確定這樣做的效果如何,但是將兩個格式化對象都緩存為ThreadStatic實例字段。

PS,我確定這是一個錯誤,但是請注意,在使用MemoryStream之前,請先對其進行處置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM