簡體   English   中英

復雜.Net對象圖的快速讀/寫

[英]Fast Read/Write of Complex .Net Object Graph

我有自己用C#編寫的數據結構(結構非常復雜)。 我需要序列化和反序列化結構。 磁盤中序列化文件的大小有時可能非常大(接近1 GB),但也可能很小(基於存儲的記錄數)。 我有以下要求:

  1. 序列化和反序列化應該非常快
  2. 我應該能夠部分反序列化一個大文件(即只訪問一些相關的記錄),因為如果我從磁盤反序列化整個文件,內存使用率將太高。
  3. 應該是線程安全的,因為多個進程可以從文件中寫入/讀取記錄

我知道這聽起來像我需要一個數據庫,但由於多種原因我不能使用它。 我嘗試通過實現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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM