2011-06-14 40 views
4

我想讀取和寫入Guids數組到AppFabric緩存。我的配置文件顯示它正在將此序列化到Xml,這意味着事情進展太慢。 A Guid[20000]需要60 ms來添加到緩存中,而類似大小的int[80000]需要10 ms。我認爲Guid數組肯定看起來像是內部某個字節數組。什麼是最快的方式來達到這個目標,同時儘可能地產生細小的絨毛?我知道我將在緩存中添加哪些內容,並且數據不會特別持久,因此我不關心序列化類信息。序列化Guid []快速二進制存儲在C#AppFabric

回答

4

我會如果串行化驚訝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); 
    } 
} 
2

使用Guid。 ToByteArray()

Guid[] yourArray = ...; 
byte[][] serializedArray = yourArray.Select(x => x.ToByteArray()).ToArray(); 

你甚至可以將其序列化到1個維陣列中,由於的Guid字節數組的長度是已知的(16):

byte[] serializedArray = yourArray.SelectMany(x => x.ToByteArray()).ToArray();