Skip to content

Commit b4e74ce

Browse files
committed
Change all StringBuilder and StringWriter allocations to new ThreadStatic caches
1 parent 5a141b7 commit b4e74ce

21 files changed

Lines changed: 149 additions & 255 deletions

src/ServiceStack.Text/Common/DateTimeSerializer.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using ServiceStack.Text.Json;
1818
using ServiceStack.Text.Support;
1919
using System.Text.RegularExpressions;
20+
using ServiceStack.Text.Pools;
2021

2122
namespace ServiceStack.Text.Common
2223
{
@@ -637,11 +638,11 @@ public static void WriteWcfJsonDate(TextWriter writer, DateTime dateTime)
637638

638639
public static string ToWcfJsonDate(DateTime dateTime)
639640
{
640-
var sb = new StringBuilder();
641+
var sb = StringBuilderThreadStatic.Allocate();
641642
using (var writer = new StringWriter(sb))
642643
{
643644
WriteWcfJsonDate(writer, dateTime);
644-
return sb.ToString();
645+
return StringBuilderThreadStatic.ReturnAndFree(sb);
645646
}
646647
}
647648

@@ -669,11 +670,11 @@ public static void WriteWcfJsonDateTimeOffset(TextWriter writer, DateTimeOffset
669670

670671
public static string ToWcfJsonDateTimeOffset(DateTimeOffset dateTimeOffset)
671672
{
672-
var sb = new StringBuilder();
673+
var sb = StringBuilderThreadStatic.Allocate();
673674
using (var writer = new StringWriter(sb))
674675
{
675676
WriteWcfJsonDateTimeOffset(writer, dateTimeOffset);
676-
return sb.ToString();
677+
return StringBuilderThreadStatic.ReturnAndFree(sb);
677678
}
678679
}
679680
}

src/ServiceStack.Text/Common/DeserializeDictionary.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.Threading;
1919
using System.Linq;
2020
using ServiceStack.Text.Json;
21+
using ServiceStack.Text.Pools;
2122

2223
namespace ServiceStack.Text.Common
2324
{
@@ -287,15 +288,15 @@ public static object ParseDictionaryType(string value, Type createMapType, Type[
287288

288289
private static string GetTypesKey(params Type[] types)
289290
{
290-
var sb = new StringBuilder(256);
291+
var sb = StringBuilderThreadStatic.Allocate();
291292
foreach (var type in types)
292293
{
293294
if (sb.Length > 0)
294295
sb.Append(">");
295296

296297
sb.Append(type.FullName);
297298
}
298-
return sb.ToString();
299+
return StringBuilderThreadStatic.ReturnAndFree(sb);
299300
}
300301
}
301302
}

src/ServiceStack.Text/Common/DeserializeKeyValuePair.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System.Threading;
2020
using System.Linq;
2121
using ServiceStack.Text.Json;
22+
using ServiceStack.Text.Pools;
2223

2324
namespace ServiceStack.Text.Common
2425
{
@@ -124,15 +125,15 @@ public static object ParseKeyValuePairType(string value, Type createMapType, Typ
124125

125126
private static string GetTypesKey(params Type[] types)
126127
{
127-
var sb = new StringBuilder(256);
128+
var sb = StringBuilderThreadStatic.Allocate();
128129
foreach (var type in types)
129130
{
130131
if (sb.Length > 0)
131132
sb.Append(">");
132133

133134
sb.Append(type.FullName);
134135
}
135-
return sb.ToString();
136+
return StringBuilderThreadStatic.ReturnAndFree(sb);
136137
}
137138
}
138139
}

src/ServiceStack.Text/CsvSerializer.cs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using ServiceStack.Reflection;
1010
using ServiceStack.Text.Common;
1111
using ServiceStack.Text.Jsv;
12+
using ServiceStack.Text.Pools;
1213

1314
namespace ServiceStack.Text
1415
{
@@ -86,25 +87,19 @@ internal static ParseStringDelegate GetReadFn(Type type)
8687

8788
public static string SerializeToCsv<T>(IEnumerable<T> records)
8889
{
89-
var sb = new StringBuilder();
90-
using (var writer = new StringWriter(sb, CultureInfo.InvariantCulture))
91-
{
92-
writer.WriteCsv(records);
93-
return sb.ToString();
94-
}
90+
var writer = StringWriterThreadStatic.Allocate();
91+
writer.WriteCsv(records);
92+
return StringWriterThreadStatic.ReturnAndFree(writer);
9593
}
9694

9795
public static string SerializeToString<T>(T value)
9896
{
9997
if (value == null) return null;
10098
if (typeof(T) == typeof(string)) return value as string;
10199

102-
var sb = new StringBuilder();
103-
using (var writer = new StringWriter(sb, CultureInfo.InvariantCulture))
104-
{
105-
CsvSerializer<T>.WriteObject(writer, value);
106-
}
107-
return sb.ToString();
100+
var writer = StringWriterThreadStatic.Allocate();
101+
CsvSerializer<T>.WriteObject(writer, value);
102+
return StringWriterThreadStatic.ReturnAndFree(writer);
108103
}
109104

110105
public static void SerializeToWriter<T>(T value, TextWriter writer)

src/ServiceStack.Text/Json/JsonTypeSerializer.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Text;
88
using ServiceStack.Text.Common;
9+
using ServiceStack.Text.Pools;
910

1011
namespace ServiceStack.Text.Json
1112
{
@@ -426,7 +427,7 @@ public static string Unescape(string input)
426427
var length = input.Length;
427428
int start = 0;
428429
int count = 0;
429-
StringBuilder output = new StringBuilder(length);
430+
var output = StringBuilderThreadStatic.Allocate();
430431
for (; count < length;)
431432
{
432433
if (input[count] == JsonUtils.QuoteChar)
@@ -488,7 +489,7 @@ public static string Unescape(string input)
488489
{
489490
var unicodeString = input.Substring(count + 1, 4);
490491
var unicodeIntVal = UInt32.Parse(unicodeString, NumberStyles.HexNumber);
491-
output.Append(JsonTypeSerializer.ConvertFromUtf32((int)unicodeIntVal));
492+
output.Append(ConvertFromUtf32((int)unicodeIntVal));
492493
count += 5;
493494
}
494495
else
@@ -500,16 +501,16 @@ public static string Unescape(string input)
500501
if (count + 4 < length)
501502
{
502503
var unicodeString = input.Substring(count + 1, 4);
503-
var unicodeIntVal = UInt32.Parse(unicodeString, NumberStyles.HexNumber);
504-
output.Append(JsonTypeSerializer.ConvertFromUtf32((int)unicodeIntVal));
504+
var unicodeIntVal = uint.Parse(unicodeString, NumberStyles.HexNumber);
505+
output.Append(ConvertFromUtf32((int)unicodeIntVal));
505506
count += 5;
506507
}
507508
else
508509
if (count + 2 < length)
509510
{
510511
var unicodeString = input.Substring(count + 1, 2);
511-
var unicodeIntVal = UInt32.Parse(unicodeString, NumberStyles.HexNumber);
512-
output.Append(JsonTypeSerializer.ConvertFromUtf32((int)unicodeIntVal));
512+
var unicodeIntVal = uint.Parse(unicodeString, NumberStyles.HexNumber);
513+
output.Append(ConvertFromUtf32((int)unicodeIntVal));
513514
count += 3;
514515
}
515516
else
@@ -530,7 +531,7 @@ public static string Unescape(string input)
530531
}
531532
}
532533
output.Append(input, start, length - start);
533-
return output.ToString();
534+
return StringBuilderThreadStatic.ReturnAndFree(output);
534535
}
535536

536537
/// <summary>

src/ServiceStack.Text/JsonSerializer.Generic.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Reflection;
1717
using ServiceStack.Text.Common;
1818
using ServiceStack.Text.Json;
19+
using ServiceStack.Text.Pools;
1920

2021
namespace ServiceStack.Text
2122
{
@@ -54,12 +55,9 @@ public string SerializeToString(T value)
5455
return result;
5556
}
5657

57-
var sb = new StringBuilder();
58-
using (var writer = new StringWriter(sb))
59-
{
60-
JsonWriter<T>.WriteObject(writer, value);
61-
}
62-
return sb.ToString();
58+
var writer = StringWriterThreadStatic.Allocate();
59+
JsonWriter<T>.WriteObject(writer, value);
60+
return StringWriterThreadStatic.ReturnAndFree(writer);
6361
}
6462

6563
public void SerializeToWriter(T value, TextWriter writer)

src/ServiceStack.Text/JsonSerializer.cs

Lines changed: 18 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using System.Text;
1818
using ServiceStack.Text.Common;
1919
using ServiceStack.Text.Json;
20+
using ServiceStack.Text.Pools;
2021

2122
namespace ServiceStack.Text
2223
{
@@ -54,57 +55,7 @@ public static object DeserializeFromReader(TextReader reader, Type type)
5455
{
5556
return DeserializeFromString(reader.ReadToEnd(), type);
5657
}
57-
58-
[ThreadStatic] //Reuse the thread static StringBuilder when serializing to strings
59-
private static StringBuilderWriter LastWriter;
60-
61-
internal class StringBuilderWriter : IDisposable
62-
{
63-
protected StringBuilder sb;
64-
protected StringWriter writer;
65-
66-
public StringWriter Writer
67-
{
68-
get { return writer; }
69-
}
70-
71-
public StringBuilderWriter()
72-
{
73-
this.sb = new StringBuilder();
74-
this.writer = new StringWriter(sb, CultureInfo.InvariantCulture);
75-
}
76-
77-
public static StringBuilderWriter Create()
78-
{
79-
var ret = LastWriter;
80-
if (JsConfig.ReuseStringBuffer && ret != null)
81-
{
82-
LastWriter = null;
83-
ret.sb.Clear();
84-
return ret;
85-
}
86-
87-
return new StringBuilderWriter();
88-
}
89-
90-
public override string ToString()
91-
{
92-
return sb.ToString();
93-
}
94-
95-
public void Dispose()
96-
{
97-
if (JsConfig.ReuseStringBuffer)
98-
{
99-
LastWriter = this;
100-
}
101-
else
102-
{
103-
Writer.Dispose();
104-
}
105-
}
106-
}
107-
58+
10859
public static string SerializeToString<T>(T value)
10960
{
11061
if (value == null || value is Delegate) return null;
@@ -120,36 +71,32 @@ public static string SerializeToString<T>(T value)
12071
return result;
12172
}
12273

123-
using (var sb = StringBuilderWriter.Create())
74+
var writer = StringWriterThreadStatic.Allocate();
75+
if (typeof(T) == typeof(string))
12476
{
125-
if (typeof(T) == typeof(string))
126-
{
127-
JsonUtils.WriteString(sb.Writer, value as string);
128-
}
129-
else
130-
{
131-
JsonWriter<T>.WriteRootObject(sb.Writer, value);
132-
}
133-
return sb.ToString();
77+
JsonUtils.WriteString(writer, value as string);
13478
}
79+
else
80+
{
81+
JsonWriter<T>.WriteRootObject(writer, value);
82+
}
83+
return StringWriterThreadStatic.ReturnAndFree(writer);
13584
}
13685

13786
public static string SerializeToString(object value, Type type)
13887
{
13988
if (value == null) return null;
14089

141-
using (var sb = StringBuilderWriter.Create())
90+
var writer = StringWriterThreadStatic.Allocate();
91+
if (type == typeof(string))
14292
{
143-
if (type == typeof(string))
144-
{
145-
JsonUtils.WriteString(sb.Writer, value as string);
146-
}
147-
else
148-
{
149-
JsonWriter.GetWriteFn(type)(sb.Writer, value);
150-
}
151-
return sb.ToString();
93+
JsonUtils.WriteString(writer, value as string);
94+
}
95+
else
96+
{
97+
JsonWriter.GetWriteFn(type)(writer, value);
15298
}
99+
return StringWriterThreadStatic.ReturnAndFree(writer);
153100
}
154101

155102
public static void SerializeToWriter<T>(T value, TextWriter writer)

src/ServiceStack.Text/Jsv/JsvSerializer.Generic.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,9 @@ public string SerializeToString(T value)
5353
if (value == null) return null;
5454
if (value is string) return value as string;
5555

56-
var sb = new StringBuilder();
57-
using (var writer = new StringWriter(sb))
58-
{
59-
JsvWriter<T>.WriteObject(writer, value);
60-
}
61-
return sb.ToString();
56+
var writer = StringWriterThreadStatic.Allocate();
57+
JsvWriter<T>.WriteObject(writer, value);
58+
return StringWriterThreadStatic.ReturnAndFree(writer);
6259
}
6360
}
6461
}

src/ServiceStack.Text/JsvFormatter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public static string Format(string serializedText)
2525
if (string.IsNullOrEmpty(serializedText)) return null;
2626

2727
var tabCount = 0;
28-
var sb = new StringBuilder();
28+
var sb = StringBuilderThreadStatic.Allocate();
2929
var firstKeySeparator = true;
3030
var inString = false;
3131

@@ -87,7 +87,7 @@ public static string Format(string serializedText)
8787
}
8888
}
8989

90-
return sb.ToString();
90+
return StringBuilderThreadStatic.ReturnAndFree(sb);
9191
}
9292

9393
private static void AppendTabLine(StringBuilder sb, int tabCount)

src/ServiceStack.Text/ListExtensions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using System.Text;
8+
using ServiceStack.Text;
89
using ServiceStack.Text.Common;
910

1011
namespace ServiceStack
@@ -18,14 +19,14 @@ public static string Join<T>(this IEnumerable<T> values)
1819

1920
public static string Join<T>(this IEnumerable<T> values, string seperator)
2021
{
21-
var sb = new StringBuilder();
22+
var sb = StringBuilderThreadStatic.Allocate();
2223
foreach (var value in values)
2324
{
2425
if (sb.Length > 0)
2526
sb.Append(seperator);
2627
sb.Append(value);
2728
}
28-
return sb.ToString();
29+
return StringBuilderThreadStatic.ReturnAndFree(sb);
2930
}
3031

3132
public static bool IsNullOrEmpty<T>(this List<T> list)

0 commit comments

Comments
 (0)