Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 98bf63b

Browse files
committed
Add DirectStreamWriter to optimize SerializeJsonToStream
Method | Mean | StdDev | Gen 0 | Allocated | ------------------------------------------------------- |--------------- |------------ |------- |---------- | SerializeJsonStringToStream | 943.4880 ns | 6.5404 ns | 1.6586 | 5.35 kB | SerializeJsonString256ToStream | 1,757.6884 ns | 17.4944 ns | 1.6159 | 5.35 kB | SerializeJsonString512ToStream | 2,535.0001 ns | 28.8410 ns | 1.6159 | 5.35 kB | SerializeJsonString4096ToStream | 14,164.6205 ns | 106.4879 ns | 0.9481 | 5.35 kB | SerializeJsonStringToStreamUsingDirectStreamWriter | 538.6769 ns | 1.8403 ns | 0.0496 | 231 B | SerializeJsonString256ToStreamUsingDirectStreamWriter | 1,653.3597 ns | 4.4564 ns | 0.0473 | 462 B | SerializeJsonString512ToStreamUsingDirectStreamWriter | 2,650.3099 ns | 4.0931 ns | 0.8545 | 2.98 kB | SerializeJsonString4096ToStreamUsingDirectStreamWriter | 14,588.9268 ns | 38.9110 ns | 1.0905 | 5.53 kB |
1 parent 078ccec commit 98bf63b

9 files changed

+137
-7
lines changed

benchmarks/ServiceStack.Text.Benchmarks/JsonSerializationBenchmarks.cs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public class JsonSerializationBenchmarks
6969
static ModelWithCommonTypes commonTypesModel = ModelWithCommonTypes.Create(3);
7070
static MemoryStream stream = new MemoryStream(16384);
7171
const string serializedString = "this is the test string";
72+
readonly string serializedString256 = new string('t', 256);
73+
readonly string serializedString512 = new string('t', 512);
74+
readonly string serializedString4096 = new string('t', 4096);
7275

7376
[Benchmark]
7477
public void SerializeJsonAllTypes()
@@ -95,6 +98,27 @@ public void SerializeJsonStringToStream()
9598
JsonSerializer.SerializeToStream<string>(serializedString, stream);
9699
}
97100

101+
[Benchmark]
102+
public void SerializeJsonString256ToStream()
103+
{
104+
stream.Position = 0;
105+
JsonSerializer.SerializeToStream<string>(serializedString256, stream);
106+
}
107+
108+
[Benchmark]
109+
public void SerializeJsonString512ToStream()
110+
{
111+
stream.Position = 0;
112+
JsonSerializer.SerializeToStream<string>(serializedString512, stream);
113+
}
114+
115+
[Benchmark]
116+
public void SerializeJsonString4096ToStream()
117+
{
118+
stream.Position = 0;
119+
JsonSerializer.SerializeToStream<string>(serializedString4096, stream);
120+
}
121+
98122
[Benchmark]
99123
public void SerializeJsonStringToStreamDirectly()
100124
{
@@ -105,28 +129,54 @@ public void SerializeJsonStringToStreamDirectly()
105129
}
106130

107131

108-
[Benchmark]
132+
// [Benchmark]
109133
public void SerializeJsonAllTypesToStream()
110134
{
111135
stream.Position = 0;
112136
JsonSerializer.SerializeToStream<ModelWithAllTypes>(allTypesModel, stream);
113137
}
114138

115-
[Benchmark]
139+
// [Benchmark]
116140
public void SerializeJsonCommonTypesToStream()
117141
{
118142
stream.Position = 0;
119143
JsonSerializer.SerializeToStream<ModelWithCommonTypes>(commonTypesModel, stream);
120144
}
121145

122-
/* [Benchmark]
146+
[Benchmark]
123147
public void SerializeJsonStringToStreamUsingDirectStreamWriter()
124148
{
125149
stream.Position = 0;
126-
var writer = new DirectStreamWriter(stream);
150+
var writer = new DirectStreamWriter(stream, JsonSerializer.UTF8Encoding);
127151
JsonWriter<string>.WriteRootObject(writer, serializedString);
128152
writer.Flush();
129153
}
130-
*/
154+
155+
[Benchmark]
156+
public void SerializeJsonString256ToStreamUsingDirectStreamWriter()
157+
{
158+
stream.Position = 0;
159+
var writer = new DirectStreamWriter(stream, JsonSerializer.UTF8Encoding);
160+
JsonWriter<string>.WriteRootObject(writer, serializedString256);
161+
writer.Flush();
162+
}
163+
164+
[Benchmark]
165+
public void SerializeJsonString512ToStreamUsingDirectStreamWriter()
166+
{
167+
stream.Position = 0;
168+
var writer = new DirectStreamWriter(stream, JsonSerializer.UTF8Encoding);
169+
JsonWriter<string>.WriteRootObject(writer, serializedString512);
170+
writer.Flush();
171+
}
172+
173+
[Benchmark]
174+
public void SerializeJsonString4096ToStreamUsingDirectStreamWriter()
175+
{
176+
stream.Position = 0;
177+
var writer = new DirectStreamWriter(stream, JsonSerializer.UTF8Encoding);
178+
JsonWriter<string>.WriteRootObject(writer, serializedString4096);
179+
writer.Flush();
180+
}
131181
}
132182
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.IO;
3+
using System.Text;
4+
5+
namespace ServiceStack.Text
6+
{
7+
public class DirectStreamWriter : TextWriter
8+
{
9+
private const int optimizedBufferLength = 256;
10+
private const int maxBufferLength = 1024;
11+
12+
private Stream stream;
13+
private StreamWriter writer = null;
14+
private char[] curChar = new char[1];
15+
16+
private Encoding encoding;
17+
public override Encoding Encoding => encoding;
18+
19+
public DirectStreamWriter(Stream stream, Encoding encoding)
20+
{
21+
this.stream = stream;
22+
this.encoding = encoding;
23+
}
24+
25+
public override void Write(string s)
26+
{
27+
if (s.Length <= optimizedBufferLength)
28+
{
29+
byte[] buffer = Encoding.GetBytes(s);
30+
stream.Write(buffer, 0, buffer.Length);
31+
}
32+
else
33+
{
34+
if (writer == null)
35+
writer = new StreamWriter(stream, Encoding, s.Length < maxBufferLength ? s.Length : maxBufferLength);
36+
37+
writer.Write(s);
38+
writer.Flush();
39+
}
40+
}
41+
42+
public override void Write(char c)
43+
{
44+
curChar[0] = c;
45+
46+
byte[] buffer = Encoding.GetBytes(curChar);
47+
stream.Write(buffer, 0, buffer.Length);
48+
}
49+
50+
public override void Flush()
51+
{
52+
if (writer != null)
53+
{
54+
writer.Flush();
55+
}
56+
else
57+
{
58+
stream.Flush();
59+
}
60+
}
61+
}
62+
}

src/ServiceStack.Text/JsonSerializer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,15 @@ public static void SerializeToStream<T>(T value, Stream stream)
147147
}
148148
else
149149
{
150-
var writer = new StreamWriter(stream, UTF8Encoding);
150+
var writer = new DirectStreamWriter(stream, UTF8Encoding);
151151
JsonWriter<T>.WriteRootObject(writer, value);
152152
writer.Flush();
153153
}
154154
}
155155

156156
public static void SerializeToStream(object value, Type type, Stream stream)
157157
{
158-
var writer = new StreamWriter(stream, UTF8Encoding);
158+
var writer = new DirectStreamWriter(stream, UTF8Encoding);
159159
JsonWriter.GetWriteFn(type)(writer, value);
160160
writer.Flush();
161161
}

src/ServiceStack.Text/ServiceStack.Text.Android.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@
141141
<Compile Include="DateTimeExtensions.cs">
142142
<SubType>Code</SubType>
143143
</Compile>
144+
<Compile Include="DirectStreamWriter.cs">
145+
<SubType>Code</SubType>
146+
</Compile>
144147
<Compile Include="CsvAttribute.cs" />
145148
<Compile Include="Env.cs">
146149
<SubType>Code</SubType>

src/ServiceStack.Text/ServiceStack.Text.AndroidIndie.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@
139139
<Compile Include="DateTimeExtensions.cs">
140140
<SubType>Code</SubType>
141141
</Compile>
142+
<Compile Include="DirectStreamWriter.cs">
143+
<SubType>Code</SubType>
144+
</Compile>
142145
<Compile Include="CsvAttribute.cs" />
143146
<Compile Include="Env.cs">
144147
<SubType>Code</SubType>

src/ServiceStack.Text/ServiceStack.Text.PCL.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@
134134
<Compile Include="DateTimeExtensions.cs">
135135
<SubType>Code</SubType>
136136
</Compile>
137+
<Compile Include="DirectStreamWriter.cs">
138+
<SubType>Code</SubType>
139+
</Compile>
137140
<Compile Include="CsvAttribute.cs" />
138141
<Compile Include="Env.cs">
139142
<SubType>Code</SubType>

src/ServiceStack.Text/ServiceStack.Text.SL5.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@
157157
<Compile Include="DateTimeExtensions.cs">
158158
<SubType>Code</SubType>
159159
</Compile>
160+
<Compile Include="DirectStreamWriter.cs">
161+
<SubType>Code</SubType>
162+
</Compile>
160163
<Compile Include="CsvAttribute.cs" />
161164
<Compile Include="Env.cs">
162165
<SubType>Code</SubType>

src/ServiceStack.Text/ServiceStack.Text.Signed.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@
193193
<Compile Include="DateTimeExtensions.cs">
194194
<SubType>Code</SubType>
195195
</Compile>
196+
<Compile Include="DirectStreamWriter.cs">
197+
<SubType>Code</SubType>
198+
</Compile>
196199
<Compile Include="CsvAttribute.cs" />
197200
<Compile Include="Env.cs">
198201
<SubType>Code</SubType>

src/ServiceStack.Text/ServiceStack.Text.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@
187187
<Compile Include="DateTimeExtensions.cs">
188188
<SubType>Code</SubType>
189189
</Compile>
190+
<Compile Include="DirectStreamWriter.cs">
191+
<SubType>Code</SubType>
192+
</Compile>
190193
<Compile Include="CsvAttribute.cs" />
191194
<Compile Include="Env.cs">
192195
<SubType>Code</SubType>

0 commit comments

Comments
 (0)