3

現在、json.net を使用して、中サイズのオブジェクト コレクションである文字列を逆シリアル化しています。合計〜7000アイテム。

各項目には 4 つの同一の文字列の繰り返しグループがあり、メモリ プロファイリングでは、ネストなどに応じて約 40,000 の参照が作成されます。

シリアライザーが同一の文字列ごとに同じ参照を使用するようにする方法はありますか?

JSON の例:

  [{
    "name":"jon bones",
    "groups":[{
        "groupName":"Region",
        "code":"1"
    },{
        "groupName":"Class",
        "code":"4"
    }]
},
{
    "name":"Swan moans",
    "groups":[{
        "groupName":"Region",
        "code":"12"
    },{
        "groupName":"Class",
        "code":"1"
    }]
}]

例を追加しました。ご覧のとおり、groupName の値はほとんどすべてのオブジェクトで繰り返されます。関連するコードのみが変更されます。それほど大きな懸念事項ではありませんが、データセットが大きくなるにつれて、割り当てをあまり増やしたくありません。

また、「コード」が繰り返されるように見えるかもしれませんが、それは人それぞれです。基本的に、同じオブジェクトの複数の識別子。

4

2 に答える 2

1

他の回答で指摘されているように、その割り当ての有効期間のため、 String.Intern の使用には非常に注意する必要があります。頻繁に使用される文字列の小さなセットの場合、これが適切な場合があります。

このシナリオでは、.Net の XML シリアライザーのパターンに従うことにしました。彼らはクラス呼び出し "System.Xml.NameTable" を使用して、XML ドキュメント内の一意の文字列を解決します。上記の「dbc」で提供された実装パターンに従いましたが、String.Intern の代わりに NameTable を使用しました。

public class JsonNameTable
    : System.Xml.NameTable
{
}

public class JsonNameTableConverter
    : JsonConverter
{
    private JsonNameTable _nameTable;
    public JsonNameTableConverter(JsonNameTable nameTable)
    {
        _nameTable = nameTable;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var s = reader.TokenType == JsonToken.String ? (string)reader.Value : (string)Newtonsoft.Json.Linq.JToken.Load(reader); // Check is in case the value is a non-string literal such as an integer.
        if (s != null)
        {
            s = _nameTable.Add(s);
        }
        return s;
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

そして、使用法コードで、コンバーターを Json 設定に設定します

JsonNameTable nameTable = new JsonNameTable();
settings.Converters.Add(new JsonNameTableConverter(nameTable));

これにより、文字列を共有し、JsonNameTable への参照を使用して文字列の有効期間を制御できます。

ここで改善できる可能性があります。NameTable は、char[]、開始インデックス、および終了インデックスを指定すると、実際には既存の文字列を返します。ストリームから文字列が読み取られる 1 レベル下の nameTable を取得して、重複文字列の作成を回避することも可能です。ただし、Json.Netでそれを行う方法がわかりませんでした

于 2016-09-21T00:16:45.897 に答える