簡體   English   中英

序列化時間太長

[英]Serialization takes too long

每次添加新的 object 時,我都會序列化列表中包含的所有對象(如果應用程序崩潰,這是一種歷史記錄)。

添加前約 20 個對象時,序列化在一毫秒內完成,但從現在開始,每個新添加的 object 都將花費越來越長的時間(如果我再添加 10 個,序列化可能需要 10 分鍾)。

正如我所說,這是一段歷史。 因此,如果我重新啟動應用程序,JSON 文件中的每個 object 都會添加回列表中。 讓我們承認在關閉應用程序之前我有 20 個對象。 現在我可以再添加 20 個對象,因此它將在一毫秒內序列化 40 個。 再一次,如果我添加更多對象,我將不得不關閉並重新啟動應用程序。

我不明白為什么應用程序的同一實例中的多個序列化需要這么長時間。

下面是序列化代碼:

public static void SerializeAll()
{
    string output = JsonConvert.SerializeObject(ListOfModelToSerialize, Formatting.Indented);
    IO.StreamWriter writer = new IO.StreamWriter("A:\history.json");
    writer.Write(output);
    writer.Close();
}

反序列化代碼:

public static List<ModelToSerialize> DeserializeAll()
{
    if (IO.File.Exists("A:\history.json"))
    {
        string input = IO.File.ReadAllText("A:\history.json");
        var result = JsonConvert.DeserializeObject<List<ModelToSerialize>>(input);
        return result;
    }
    else
    {
        return new List<ModelToSerialize>();
    }
}

而且我只從我的 model 序列化 4 個屬性。 這是序列化的 model output:

{
  "an_integer": 1,
  "a_string": "...",
  "a_list_of_string": [],
  "another_list_of_string": []
}

更新 1:

我正在序列化的 integer (ID) 似乎是問題所在。 事實上,在創建 model 時並未分配此 ID,因為每次將新的 object 添加到列表時它都會更改,因為列表是按字母順序排序的。 所以要獲得 ID,我這樣做:

[JsonProperty(PropertyName = "id")]
public int Id
{
    get 
    {
        if (_id > 0) 
        {
            return _id;
        }
        else
        {
            int id = Properties.Settings.Default.PREVIOUS_MAX_ID + 1;

            foreach (File file in _directory.Files)
            {
                if (file == this) 
                {
                    return id; 
                }
                else if (file.Id == id)
                {
                    id += 1;
                }
            }

            return 0;
        }
    }
}

所以app重啟后序列化前20個對象不需要更長的時間的原因是在反序列化時直接分配了ID。

所以我必須適應ID檢索。

更新 2:

由於 ID 檢索是性能問題,我通過在每次添加新的 object 時將 ID 分配給每個 object 來修復它。 像這樣,當調用 object ID 時,model 中不再有迭代。

以下塊是我的對象列表的自定義Add()方法:

public new void Add(File file)
{
    if (!base.Contains(file))
    {
        base.Add(file);
        base.Sort(new Comparer());

        for (int i = 0; i < Count; i++)
        {
            this[i].Id = Properties.Settings.Default.PREVIOUS_MAX_ID + i;
        }
    }
}

我向應用程序的當前實例添加了大約 100 個新對象,序列化不再需要數年時間。

序列化(JSON 等)最好用於將離散的數據位從一種介質傳輸到另一種介質,例如進行網絡 API 調用。 它還可以用於將數據存儲到磁盤中。

但是當您經常更新數據時,這不是一個好的選擇,因為最流行的格式(JSON、XML)沒有結構化,因此新數據只能附加到現有數據中。 這就是為什么它每次都需要序列化。 當然,隨着數據變大,序列化需要更長的時間。

出於您的目的,我建議使用 SQLite 之類的數據庫。 如果數據不適合列,您仍然可以將每個單獨的行序列化為 JSON,但是您可以將 append 新數據寫入數據庫,而無需重寫舊數據。 如果您使用事務,即使您的應用程序崩潰,您也可以確保數據保持其完整性。

對於任何類型的性能問題,我建議測量,最好使用性能分析器,它可以准確地告訴你代碼的哪一部分是慢的。

一些一般性建議

  • 您可能希望限制保留多少歷史記錄。 否則,當您積累對象時,您的應用程序可能會變得越來越慢。 這也可以讓您測試最壞情況下的性能。
  • 使用更快的序列化程序,雖然 json.net 很好,但使用二進制序列化的一些變體,如 protobuf.net,通常會導致更少的數據和時間( 基准測試),但代價是人類不可讀。 您也可以考慮使用像lz4這樣的快速壓縮器來減小文件大小,從而降低磁盤性能。
  • 更改您的 model,這樣您就不必覆蓋所有數據。 序列化到不同的文件,或者使用一些序列化方法,讓你 append 消息到同一個文件。
  • 限制保存頻率。 您可能不需要為每次更改保存歷史記錄,每 5 秒左右保存一次就足夠了。
  • 如果您還沒有這樣做,請確保至少以異步方式保存數據,以免阻塞 UI 線程。 這可能需要某種方式以線程安全的方式訪問您的數據,以確保它在序列化時不會更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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