我正在尝试读取和编写Guids数组到AppFabric缓存。我的探查器向我显示它将此序列化为Xml,这意味着事情进展得太慢了。 Guid[20000]
需要60 ms才能添加到缓存,而类似大小的int[80000]
需要10 ms。我想要一个Guids数组肯定在内部看起来像一个字节数组。达到这个目标的最快方法是什么,同时产生尽可能少的meta-fluff?我知道我将在缓存中添加和访问,并且数据不会特别持久,因此我不关心序列化类信息。
答案 0 :(得分:4)
如果AppFabric缓存使用的序列化使用了除WCF的二进制编写器以外的任何东西,我会感到惊讶,所以如果是这种情况(看起来像这样),那么差异可以通过对数组的处理来解释二进制格式。某些基本类型的数组具有special node type,允许它们以二进制格式非常有效地存储。 int(和byte)是其中一些类型。 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);
}
}
答案 1 :(得分:2)
使用Guid。ToByteArray()
Guid[] yourArray = ...;
byte[][] serializedArray = yourArray.Select(x => x.ToByteArray()).ToArray();
你甚至可以将它序列化为一维数组,因为Guid字节数组的长度是已知的(16):
byte[] serializedArray = yourArray.SelectMany(x => x.ToByteArray()).ToArray();