diff --git a/src/UglyToad.PdfPig.Tokenization/NumericTokenizer.cs b/src/UglyToad.PdfPig.Tokenization/NumericTokenizer.cs
index c6b75a4f..e5c56fc8 100644
--- a/src/UglyToad.PdfPig.Tokenization/NumericTokenizer.cs
+++ b/src/UglyToad.PdfPig.Tokenization/NumericTokenizer.cs
@@ -8,6 +8,8 @@
internal class NumericTokenizer : ITokenizer
{
+ private static readonly StringBuilderPool StringBuilderPool = new StringBuilderPool(10);
+
private const byte Zero = 48;
private const byte Nine = 57;
@@ -21,7 +23,7 @@
if ((currentByte >= Zero && currentByte <= Nine) || currentByte == '-' || currentByte == '+' || currentByte == '.')
{
- characters = new StringBuilder();
+ characters = StringBuilderPool.Borrow();
characters.Append((char)currentByte);
}
else
@@ -51,6 +53,7 @@
try
{
var str = characters.ToString();
+ StringBuilderPool.Return(characters);
switch (str)
{
diff --git a/src/UglyToad.PdfPig.Tokenization/PlainTokenizer.cs b/src/UglyToad.PdfPig.Tokenization/PlainTokenizer.cs
index 5d1f8486..8ef87512 100644
--- a/src/UglyToad.PdfPig.Tokenization/PlainTokenizer.cs
+++ b/src/UglyToad.PdfPig.Tokenization/PlainTokenizer.cs
@@ -1,11 +1,12 @@
namespace UglyToad.PdfPig.Tokenization
{
- using System.Text;
using Core;
using Tokens;
internal class PlainTokenizer : ITokenizer
{
+ private static readonly StringBuilderPool StringBuilderPool = new StringBuilderPool(10);
+
public bool ReadsNextByte { get; } = true;
public bool TryTokenize(byte currentByte, IInputBytes inputBytes, out IToken token)
@@ -17,7 +18,7 @@
return false;
}
- var builder = new StringBuilder();
+ var builder = StringBuilderPool.Borrow();
builder.Append((char)currentByte);
while (inputBytes.MoveNext())
{
@@ -38,6 +39,7 @@
}
var text = builder.ToString();
+ StringBuilderPool.Return(builder);
switch (text)
{
diff --git a/src/UglyToad.PdfPig.Tokenization/StringBuilderPool.cs b/src/UglyToad.PdfPig.Tokenization/StringBuilderPool.cs
new file mode 100644
index 00000000..7ff0ba92
--- /dev/null
+++ b/src/UglyToad.PdfPig.Tokenization/StringBuilderPool.cs
@@ -0,0 +1,65 @@
+namespace UglyToad.PdfPig.Tokenization
+{
+ using System.Collections.Generic;
+ using System.Text;
+
+ ///
+ /// A pool for s to reduce allocations during tokenization.
+ ///
+ public class StringBuilderPool
+ {
+ private readonly int capacity;
+ private readonly object locker = new object();
+ private readonly Stack pool = new Stack();
+
+ ///
+ /// Create a new holding the number of items specified by the capacity.
+ ///
+ public StringBuilderPool(int capacity = 5)
+ {
+ this.capacity = capacity;
+
+ for (var i = 0; i < capacity; i++)
+ {
+ pool.Push(new StringBuilder());
+ }
+ }
+
+ ///
+ /// Get an item from the pool, remember to return it using at the end.
+ ///
+ public StringBuilder Borrow()
+ {
+ lock (locker)
+ {
+ if (pool.Count == 0)
+ {
+ return new StringBuilder();
+ }
+
+ return pool.Pop();
+ }
+ }
+
+ ///
+ /// Returns an item to the pool of available builders.
+ ///
+ public void Return(StringBuilder instance)
+ {
+ if (instance == null)
+ {
+ return;
+ }
+
+ instance.Clear();
+
+ lock (locker)
+ {
+ if (pool.Count < capacity)
+ {
+ pool.Push(instance);
+ }
+ }
+ }
+ }
+}
diff --git a/src/UglyToad.PdfPig.Tokenization/StringTokenizer.cs b/src/UglyToad.PdfPig.Tokenization/StringTokenizer.cs
index d701df67..bc68e919 100644
--- a/src/UglyToad.PdfPig.Tokenization/StringTokenizer.cs
+++ b/src/UglyToad.PdfPig.Tokenization/StringTokenizer.cs
@@ -6,11 +6,11 @@
internal class StringTokenizer : ITokenizer
{
+ private static readonly StringBuilderPool StringBuilderPool = new StringBuilderPool(16);
public bool ReadsNextByte { get; } = false;
public bool TryTokenize(byte currentByte, IInputBytes inputBytes, out IToken token)
{
- var builder = new StringBuilder();
token = null;
if (inputBytes == null)
@@ -23,6 +23,7 @@
return false;
}
+ var builder = StringBuilderPool.Borrow();
var numberOfBrackets = 1;
var isEscapeActive = false;
var isLineBreaking = false;
@@ -177,6 +178,8 @@
encodedWith = StringToken.Encoding.Iso88591;
}
+ StringBuilderPool.Return(builder);
+
token = new StringToken(tokenStr, encodedWith);
return true;