mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-14 02:44:58 +08:00
add stringbuilder pool for tokenizers
we could replace these with spans in the next net core however for now our pools seem to increase performance by reducing gc load.
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
{
|
||||
|
65
src/UglyToad.PdfPig.Tokenization/StringBuilderPool.cs
Normal file
65
src/UglyToad.PdfPig.Tokenization/StringBuilderPool.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
namespace UglyToad.PdfPig.Tokenization
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// A pool for <see cref="StringBuilder"/>s to reduce allocations during tokenization.
|
||||
/// </summary>
|
||||
public class StringBuilderPool
|
||||
{
|
||||
private readonly int capacity;
|
||||
private readonly object locker = new object();
|
||||
private readonly Stack<StringBuilder> pool = new Stack<StringBuilder>();
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StringBuilderPool"/> holding the number of items specified by the capacity.
|
||||
/// </summary>
|
||||
public StringBuilderPool(int capacity = 5)
|
||||
{
|
||||
this.capacity = capacity;
|
||||
|
||||
for (var i = 0; i < capacity; i++)
|
||||
{
|
||||
pool.Push(new StringBuilder());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an item from the pool, remember to return it using <see cref="Return"/> at the end.
|
||||
/// </summary>
|
||||
public StringBuilder Borrow()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
if (pool.Count == 0)
|
||||
{
|
||||
return new StringBuilder();
|
||||
}
|
||||
|
||||
return pool.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an item to the pool of available builders.
|
||||
/// </summary>
|
||||
public void Return(StringBuilder instance)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
instance.Clear();
|
||||
|
||||
lock (locker)
|
||||
{
|
||||
if (pool.Count < capacity)
|
||||
{
|
||||
pool.Push(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user