From bea4458ae3fc288c4239ae8f2faca20223d5d18c Mon Sep 17 00:00:00 2001 From: Ivan Zlatanov Date: Fri, 8 Feb 2019 02:06:32 +0200 Subject: [PATCH] Significant performance optimization to the serializiation of decimals - trailing zeroes are now truncated after the serialization, avoiding the expensive division by 1.00000000000000000. --- src/JsonWriter.cs | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/JsonWriter.cs b/src/JsonWriter.cs index db192c1..1b34346 100644 --- a/src/JsonWriter.cs +++ b/src/JsonWriter.cs @@ -380,17 +380,36 @@ public void WriteValue( Decimal value ) { WriteStarted( State.Value ); - // Do not serialize trailing zeroes. The current version of the Utf8Formatter we use - // do not allow us to specify that we don't want any. - // https://stackoverflow.com/a/7983330/132690 - value /= 1.0000000000000000000000000000M; + var span = m_output.GetSpan( Constants.MaxDecimalSize ); - if ( !Utf8Formatter.TryFormat( value, m_output.GetSpan(), out var bytesWritten ) && - !Utf8Formatter.TryFormat( value, m_output.GetSpan( Constants.MaxDecimalSize ), out bytesWritten ) ) + if ( !Utf8Formatter.TryFormat( value, span, out var bytesWritten ) ) { ThrowFormatException( value ); } + // Do not serialize trailing zeroes. The current version of the Utf8Formatter we use + // do not allow us to specify that we don't want any. + if ( span[ bytesWritten - 1 ] == (Byte)'0' ) + { + // Find out if the decimal has a decimal point + var pointIndex = span.LastIndexOf( (Byte)'.' ); + + if ( pointIndex != -1 ) + { + --bytesWritten; + + while ( span[ bytesWritten - 1 ] == (Byte)'0' ) + { + --bytesWritten; + } + + if ( bytesWritten - 1 == pointIndex ) + { + --bytesWritten; + } + } + } + m_output.Advance( bytesWritten ); }