我們不缺少JSON的序列化庫,但我們缺少一個性能非常好的庫,這對于網站來說非常重要。今天我發現了Jil。
他是開源的代碼:https://github.com/kevin-montrose/Jil
在他主頁上有詳細的介紹其性能的表現,我這里就不轉述了,他最重要的特點就是性能,Emit那當然不會少了,當想讓他超越其他的庫光一個Emit肯定不行,他還有很多其他的優化。
為介紹GC的壓力,他使用了諸如builder.CommonCharBuffer這樣的功能緩沖,builder.CommonStringBuffer也是這樣的應用。
很多的方法,都標記了[MethodImpl(MethodImplOptions.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 do20 {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 else10 {11 writer.Write('-');12 copy = 1 + (uint)~number;13 }14 15 do16 {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 return11 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 return11 c < 0x21 && (12 c == 0x20 ||13 c == 0x09 ||14 c == 0x0A ||15 c == 0x0D);16 }
|
新聞熱點
疑難解答