高速Json(逆)シーケンス化オープンソースプロジェクトJilを共有

17397 ワード

JSONのシーケンス化ライブラリは欠けていませんが、非常にパフォーマンスの良いライブラリが欠けています.これはウェブサイトにとって非常に重要です.今日はJilを見つけました.
彼はオープンソースのコードです:https://github.com/kevin-montrose/Jil
彼のホームページにはその性能の表現が詳しく紹介されていますが、私はここで転記しません.彼の最も重要な特徴は性能です.Emitはもちろん少なくありません.他のライブラリの光を超えさせたいなら、Emitはきっとだめです.彼は他にも多くの最適化があります.
  • 共通バッファ
  • GCのプレッシャーを紹介するためにbuilder.CommonCharBufferのような機能バッファ、builder.CommonStringBufferもこのような応用です.
  • インライン
  • 多くの方法では、コンパイラが可能な限りインラインするように[MethodImplOperations.AggressiveInlining)]とマークされています.
  • 減少計算
  • 例えばintをstringに変換し、元のコードはこのように書かれています.
     1         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     2         static void _CustomWriteInt(TextWriter writer, int number, char[] buffer)
     3         {
     4             // Gotta special case this, we can't negate it
     5             if (number == int.MinValue)
     6             {
     7                 writer.Write("-2147483648");
     8                 return;
     9             }
    10 
    11             var ptr = InlineSerializer<object>.CharBufferSize - 1;
    12 
    13             var copy = number;
    14             if (copy < 0)
    15             {
    16                 copy = -copy;
    17             }
    18 
    19             do
    20             {
    21                 var ix = copy % 10;
    22                 copy /= 10;
    23 
    24                 buffer[ptr] = (char)('0' + ix);
    25                 ptr--;
    26             } while (copy != 0);
    27 
    28             if (number < 0)
    29             {
    30                 buffer[ptr] = '-';
    31                 ptr--;
    32             }
    33 
    34             writer.Write(buffer, ptr + 1, InlineSerializer<object>.CharBufferSize - 1 - ptr);
    35         }

    もういいと思っているのではないでしょうか.しかし、彼らは絶えず進取して、このようにしました.
     1         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     2         static void _CustomWriteInt(TextWriter writer, int number, char[] buffer)
     3         {
     4             var ptr = InlineSerializer<object>.CharBufferSize - 1;
     5 
     6             uint copy;
     7             if (number >= 0)
     8                 copy = (uint)number;
     9             else
    10             {
    11                 writer.Write('-');
    12                 copy = 1 + (uint)~number;
    13             }
    14 
    15             do
    16             {
    17                 var ix = copy % 100;
    18                 copy /= 100;
    19 
    20                 var chars = DigitPairs[ix];
    21                 buffer[ptr--] = chars.Second;
    22                 buffer[ptr--] = chars.First;
    23             } while (copy != 0);
    24 
    25             if (buffer[ptr + 1] == '0')
    26                 ++ptr;
    27 
    28             writer.Write(buffer, ptr + 1, InlineSerializer<object>.CharBufferSize - 1 - ptr);
    29         }

    その中で、あのDigitPairsは何ですか?
     1 struct TwoDigits
     2         {
     3             public readonly char First;
     4             public readonly char Second;
     5 
     6             public TwoDigits(char first, char second)
     7             {
     8                 First = first;
     9                 Second = second;
    10             }
    11         }
    12 
    13         private static readonly TwoDigits[] DigitPairs;
    14 
    15         static Methods()
    16         {
    17             DigitPairs = new TwoDigits[100];
    18             for (var i=0; i < 100; ++i)
    19                 DigitPairs[i] = new TwoDigits((char)('0' + (i / 10)), (char)+('0' + (i % 10)));
    20         }

     
    考えが高いのではないでしょうか.
     
  • 減少判定
  • もとの方法はこうだった
     1 static bool IsWhiteSpace(int c)
     2         {
     3             // per http://www.ietf.org/rfc/rfc4627.txt
     4             // insignificant whitespace in JSON is defined as 
     5             //  \u0020  - space
     6             //  \u0009  - tab
     7             //  \u000A  - new line
     8             //  \u000D  - carriage return
     9 
    10             return
    11                 c == 0x20 ||
    12                 c == 0x09 ||
    13                 c == 0x0A ||
    14                 c == 0x0D;
    15         }

    このように変えることができて、はは、実は私はこのように変えたいです.ほとんどの場合空白ではないと思うので、4回判断してから戻るのですが、私はこのように変更しました.
     1 static bool IsWhiteSpace(int c)
     2         {
     3             // per http://www.ietf.org/rfc/rfc4627.txt
     4             // insignificant whitespace in JSON is defined as 
     5             //  \u0020  - space
     6             //  \u0009  - tab
     7             //  \u000A  - new line
     8             //  \u000D  - carriage return
     9 
    10             return
    11                 c < 0x21 && (
    12                 c == 0x20 ||
    13                 c == 0x09 ||
    14                 c == 0x0A ||
    15                 c == 0x0D);
    16         }