我正在尝试将 Guid 数组读取和写入 AppFabric 缓存。我的分析器显示它正在将它序列化为 Xml,这意味着事情进展得太慢了。 Guid[20000] 添加到缓存需要 60 毫秒,而类似大小的 int[80000] 需要 10 毫秒。我认为 Guid 数组肯定看起来像内部某个地方的字节数组。达到此目的的最快方法是什么,同时产生尽可能少的元绒毛?我知道我将在哪里添加和访问缓存,并且数据不会特别持久,所以我不关心序列化类信息。

最佳答案

如果 AppFabric 缓存使用的序列化使用的不是来自 WCF 的二进制编写器,我会感到惊讶,所以如果是这种情况(似乎是这样),那么差异可以通过对二进制格式的数组的处理来解释.某些原始类型的数组有一个 special node type ,它允许它们以二进制格式非常有效地存储。 int(和字节)是其中一些类型。 Guid 不是(我不知道团队选择了什么来决定什么是“数组类型”)。因此,虽然序列化二进制格式的整数数组非常有效,但序列化 Guid 数组则不然。

正如 m0sa 建议的那样,您可以将其转换为 byte[] 并且您可能会看到很大的改进。我发现 LINQ 语法虽然更简洁,但并没有为您提供使用更传统的 for 循环可能获得的重大性能改进。我已经运行了下面的代码来比较序列化速度(我认为这将映射到 AF 缓存),并且序列化为 byte[](即使 Guid[] 到 byte[] 之间的转换)甚至比来自 int[] 的那个。

public class StackOverflow_6346646
{
    static void SerializeGuid()
    {
        Console.WriteLine("Serializing Guid[]");
        var guids = new Guid[20000];
        Random rndGen = new Random();
        for (int i = 0; i < guids.Length; i++)
        {
            guids[i] = Guid.NewGuid();
        }
        MemoryStream ms = new MemoryStream();
        Stopwatch watch = new Stopwatch();
        DataContractSerializer dcs = new DataContractSerializer(guids.GetType());
        XmlDictionaryWriter binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(ms);
        watch.Start();
        dcs.WriteObject(binaryWriter, guids);
        binaryWriter.Flush();
        watch.Stop();
        Console.WriteLine("Serialized in {0}ms, total size = {1} bytes", watch.ElapsedMilliseconds, ms.Position);
    }
    static void SerializeInt()
    {
        Console.WriteLine("Serializing int[]");
        var guids = new int[80000]; // new Guid[20000];
        Random rndGen = new Random();
        for (int i = 0; i < guids.Length; i++)
        {
            guids[i] = rndGen.Next(); // Guid.NewGuid();
        }
        MemoryStream ms = new MemoryStream();
        Stopwatch watch = new Stopwatch();
        DataContractSerializer dcs = new DataContractSerializer(guids.GetType());
        XmlDictionaryWriter binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(ms);
        watch.Start();
        dcs.WriteObject(binaryWriter, guids);
        binaryWriter.Flush();
        watch.Stop();
        Console.WriteLine("Serialized in {0}ms, total size = {1} bytes", watch.ElapsedMilliseconds, ms.Position);
    }
    static void SerializeGuidAsByteArray(bool useLinq)
    {
        Console.WriteLine("Serializing Guid[] as byte[], {0}", useLinq ? "using LINQ" : "not using LINQ");
        var guids = new Guid[20000];
        Random rndGen = new Random();
        for (int i = 0; i < guids.Length; i++)
        {
            guids[i] = Guid.NewGuid();
        }

        MemoryStream ms = new MemoryStream();
        Stopwatch watch = new Stopwatch();
        DataContractSerializer dcs = new DataContractSerializer(typeof(byte[]));
        XmlDictionaryWriter binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(ms);
        watch.Start();
        byte[] bytes;
        if (useLinq)
        {
            bytes = guids.SelectMany(x => x.ToByteArray()).ToArray();
        }
        else
        {
            bytes = new byte[guids.Length * 16];
            for (int i = 0; i < guids.Length; i++)
            {
                byte[] guidBytes = guids[i].ToByteArray();
                Buffer.BlockCopy(guidBytes, 0, bytes, 16 * i, 16);
            }
        }
        dcs.WriteObject(binaryWriter, bytes);
        binaryWriter.Flush();
        watch.Stop();
        Console.WriteLine("Serialized in {0}ms, total size = {1} bytes", watch.ElapsedMilliseconds, ms.Position);
    }
    public static void Test()
    {
        SerializeGuid();
        SerializeInt();
        SerializeGuidAsByteArray(true);
        SerializeGuidAsByteArray(false);
    }
}

关于c# - 快速将 Guid[] 序列化为二进制文件以存储在 C# AppFabric 中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6346646/

10-17 00:55