如何进一步优化(先速度然后记忆)

时间:2012-06-24 17:39:51

标签: c# .net performance optimization

我有这个小代码,它接受一个对象并将其转换为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();
    }

4 个答案:

答案 0 :(得分:3)

如果您想进一步优化,首先需要知道的是您目前花费的时间最多。你是通过分析器运行的吗?结果是什么?

我还会问自己“为我的用户提供哪些优化这些优势?”。换句话说,我是否优化了这一点,因为作为工程师,我想完善代码,或者因为它会为我提供解决方案的人们带来真正的好处?

我怀疑您花费大部分时间执行实际的序列化,更改为不同的序列化程序可能会产生最大的好处。有关替代的,更快的序列化程序,请参阅以下问题:

Fast and compact object serialization in .NET

答案 1 :(得分:2)

问题是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. 如果您对此感觉不错,请使用符合您需求的第三方serializer

答案 2 :(得分:1)

你真的没有太多办法来改进这段代码。如果您正在处理简单对象,则可以通过将BinaryFormatter替换为BinaryWriter并手动序列化每个字段/属性来改进此代码,这将是您可以获得的最快序列化。但是,只有当您通过实验确定此代码在某种程度上是您的应用程序的瓶颈时,才应采取这种极端措施。否则你可能会浪费你的时间进行微观优化。

答案 3 :(得分:0)

ThreadStatic byte[]定义为实例字段,并将其用作缓存。围绕此缓存对象包装内存流。当您在代码中使用MemoryStream时,您将执行大量的分配,重新分配和数组复制步骤,因为MemoryStream将可调整大小。还需要考虑垃圾收集的成本。

可能,虽然我不确定这会有多好,但是将格式化对象缓存为ThreadStatic个实例字段。

PS,我确定这是一个错误,但请注意您在使用之前处置了MemoryStream