Performance optimization for integer value serialization. (#1544)

* Performance optimization for integer serialization.

* Add int32 overloads for integer formatter.

* fix parameter name

* Prefer using the faster, 32 bit division code path, when possible.

* fix code formatting

* fix uint range check, add test coverage
This commit is contained in:
Mark Pflug
2017-12-20 11:08:09 +13:00
committed by James Newton-King
parent a8245a5b9e
commit 3ea750d6d6
3 changed files with 86 additions and 7 deletions
@@ -45,6 +45,20 @@ namespace Newtonsoft.Json.Tests.Benchmarks
return sw.ToString();
}
[Benchmark]
public string SerializeIntegers()
{
StringWriter sw = new StringWriter();
JsonTextWriter jsonTextWriter = new JsonTextWriter(sw);
for (int i = 0; i < 10000; i++)
{
jsonTextWriter.WriteValue(i);
}
jsonTextWriter.Flush();
return sw.ToString();
}
}
}
@@ -902,6 +902,9 @@ namespace Newtonsoft.Json.Tests
jsonWriter.WriteValue(long.MinValue);
jsonWriter.WriteValue(ulong.MaxValue);
jsonWriter.WriteValue(ulong.MinValue);
jsonWriter.WriteValue((ulong)uint.MaxValue - 1);
jsonWriter.WriteValue((ulong)uint.MaxValue);
jsonWriter.WriteValue((ulong)uint.MaxValue + 1);
jsonWriter.WriteEndArray();
}
@@ -918,7 +921,10 @@ namespace Newtonsoft.Json.Tests
9223372036854775807,
-9223372036854775808,
18446744073709551615,
0
0,
4294967294,
4294967295,
4294967296
]", sb.ToString());
}
+65 -6
View File
@@ -817,20 +817,77 @@ namespace Newtonsoft.Json
}
}
private void WriteIntegerValue(ulong uvalue, bool negative)
private void WriteIntegerValue(ulong value, bool negative)
{
if (!negative & uvalue <= 9)
if (!negative & value <= 9)
{
_writer.Write((char)('0' + uvalue));
_writer.Write((char)('0' + value));
}
else
{
int length = WriteNumberToBuffer(uvalue, negative);
int length = WriteNumberToBuffer(value, negative);
_writer.Write(_writeBuffer, 0, length);
}
}
private int WriteNumberToBuffer(ulong value, bool negative)
{
if (value <= uint.MaxValue)
{
// avoid the 64 bit division if possible
return WriteNumberToBuffer((uint)value, negative);
}
EnsureWriteBuffer();
int totalLength = MathUtils.IntLength(value);
if (negative)
{
totalLength++;
_writeBuffer[0] = '-';
}
int index = totalLength;
do
{
ulong quotient = value / 10;
ulong digit = value - (quotient * 10);
_writeBuffer[--index] = (char)('0' + digit);
value = quotient;
} while (value != 0);
return totalLength;
}
private void WriteIntegerValue(int value)
{
if (value >= 0 && value <= 9)
{
_writer.Write((char)('0' + value));
}
else
{
bool negative = value < 0;
WriteIntegerValue(negative ? (uint)-value : (uint)value, negative);
}
}
private void WriteIntegerValue(uint value, bool negative)
{
if (!negative & value <= 9)
{
_writer.Write((char)('0' + value));
}
else
{
int length = WriteNumberToBuffer(value, negative);
_writer.Write(_writeBuffer, 0, length);
}
}
private int WriteNumberToBuffer(uint value, bool negative)
{
EnsureWriteBuffer();
@@ -846,8 +903,10 @@ namespace Newtonsoft.Json
do
{
_writeBuffer[--index] = (char)('0' + value % 10);
value /= 10;
uint quotient = value / 10;
uint digit = value - (quotient * 10);
_writeBuffer[--index] = (char)('0' + digit);
value = quotient;
} while (value != 0);
return totalLength;