[英]Fast Read/Write of Complex .Net Object Graph
我有自己用C#編寫的數據結構(結構非常復雜)。 我需要序列化和反序列化結構。 磁盤中序列化文件的大小有時可能非常大(接近1 GB),但也可能很小(基於存儲的記錄數)。 我有以下要求:
我知道這聽起來像我需要一個數據庫,但由於多種原因我不能使用它。 我嘗試通過實現ISerializable來實現需求1,這使得它比使用Binary / XML序列化器中內置的.net快得多,但速度不夠快。 對於要求2是完全難倒我。
那里有人對如何解決這個問題有任何想法嗎? 我想任何不得不保存自己的大文件格式的人都必須處理類似的問題。
問候,山姆
我沒有像你在這里那樣處理過任何場景。 但是,我過去曾討論過類似的問題,這是討論的結果。 (雖然我承認我從未見過實施)。 此外,我擔心可能沒有任何簡單的直接解決方案。
假設:
一世。 要寫入的數據已排序。
解:
一世。 將數據存儲分段為多個文件。 為每個文件分配一系列排序值。 例如。 在文件1中記錄1-10000,在文件2中記錄100001-20000,依此類推。
II。 當您編寫/讀取數據時,您可以預先知道范圍,這樣您就可以達到第2點。
III。 只要兩個或多個進程請求完全相同的數據的機會較少,它也將解決第3點。
為了能夠提供更准確的解決方案,我們需要有關您要實現的目標的更多信息。
是數據樹 ,還是完整的圖表 - 即是否有任何循環引用? 如果不是, protobuf網是一個高性能的二叉樹串行器。 它支持可枚舉項的流式傳輸(因此您可以跳過記錄等 - 而不是緩沖所有內容),但要有效地尋找隨機元素,我希望您需要某種索引。
單個文件的讀/寫非常困難; 特別是,寫入可能需要移動大量的磁盤而不是預期...讀取也很棘手,可能需要同步。 使用單獨的文件會更容易......
跳過早期項目的例子; 我可能會添加一個輔助方法,但TryDeserializeWithLengthPrefix
方法將起作用......關鍵是要觀察序列化和反序列化之間我們只創建一個額外的對象。
using System;
using System.IO;
using System.Threading;
using ProtoBuf;
[ProtoContract]
class Foo {
static int count;
public static int ObjectCount { get { return count; } }
public Foo() { // track how many objects have been created...
Interlocked.Increment(ref count);
}
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public double Bar { get; set; }
}
static class Program {
static void Main() {
MemoryStream ms = new MemoryStream();
Random rand = new Random();
for (int i = 1; i <= 5000; i++) {
Foo foo = new Foo { Bar = rand.NextDouble(), Id = i };
Serializer.SerializeWithLengthPrefix(ms, foo,PrefixStyle.Base128, 1);
}
ms.Position = 0;
// skip 1000
int index = 0;
object obj;
Console.WriteLine(Foo.ObjectCount);
Serializer.NonGeneric.TryDeserializeWithLengthPrefix(
ms, PrefixStyle.Base128,
tag => ++index == 1000 ? typeof(Foo) : null, out obj);
Console.WriteLine(Foo.ObjectCount);
Console.WriteLine(((Foo)obj).Id);
}
}
我想我們需要更多關於文件實際外觀的信息......
你不能只從文件中讀取sizeof(yourstruct)的片段,並單獨處理它們讀取內存中的所有記錄嗎?
對於部分(或拆分)反序列化(我一直在看自己,如游戲級別的動態和靜態部分),我認為你必須編寫自己的序列化引擎。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.