繁体   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