mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-10-14 19:05:01 +08:00
add a bunch more performance improvements
filter provider becomes single instance and no longer has constructor parameters. tokenizers use list and stringbuilder pools to reduce allocations. system font finder becomes static to preserve file cache across all documents.
This commit is contained in:
64
src/UglyToad.PdfPig.Tokenization/ListPool.cs
Normal file
64
src/UglyToad.PdfPig.Tokenization/ListPool.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UglyToad.PdfPig.Tokenization
|
||||
{
|
||||
/// <summary>
|
||||
/// An object pool for lists.
|
||||
/// </summary>
|
||||
public class ListPool<T>
|
||||
{
|
||||
private readonly int capacity;
|
||||
private readonly object locker = new object();
|
||||
private readonly Stack<List<T>> pool = new Stack<List<T>>();
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="List{T}"/> holding the number of items specified by the capacity.
|
||||
/// </summary>
|
||||
public ListPool(int capacity = 5)
|
||||
{
|
||||
this.capacity = capacity;
|
||||
|
||||
for (var i = 0; i < capacity; i++)
|
||||
{
|
||||
pool.Push(new List<T>(10));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an item from the pool, remember to return it using <see cref="Return"/> at the end.
|
||||
/// </summary>
|
||||
public List<T> Borrow()
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
if (pool.Count == 0)
|
||||
{
|
||||
return new List<T>();
|
||||
}
|
||||
|
||||
return pool.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an item to the pool of available lists..
|
||||
/// </summary>
|
||||
public void Return(List<T> instance)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
instance.Clear();
|
||||
|
||||
lock (locker)
|
||||
{
|
||||
if (pool.Count < capacity)
|
||||
{
|
||||
pool.Push(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,6 +8,8 @@
|
||||
|
||||
internal class NameTokenizer : ITokenizer
|
||||
{
|
||||
private static readonly ListPool<byte> ListPool = new ListPool<byte>(10);
|
||||
|
||||
public bool ReadsNextByte { get; } = true;
|
||||
|
||||
public bool TryTokenize(byte currentByte, IInputBytes inputBytes, out IToken token)
|
||||
@@ -19,7 +21,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
var bytes = new List<byte>();
|
||||
var bytes = ListPool.Borrow();
|
||||
|
||||
bool escapeActive = false;
|
||||
int postEscapeRead = 0;
|
||||
@@ -90,7 +92,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
byte[] byteArray = bytes.ToArray();
|
||||
var byteArray = bytes.ToArray();
|
||||
|
||||
ListPool.Return(bytes);
|
||||
|
||||
var str = ReadHelper.IsValidUtf8(byteArray)
|
||||
? Encoding.UTF8.GetString(byteArray)
|
||||
|
@@ -6,7 +6,7 @@
|
||||
/// <summary>
|
||||
/// A pool for <see cref="StringBuilder"/>s to reduce allocations during tokenization.
|
||||
/// </summary>
|
||||
public class StringBuilderPool
|
||||
internal class StringBuilderPool
|
||||
{
|
||||
private readonly int capacity;
|
||||
private readonly object locker = new object();
|
||||
|
Reference in New Issue
Block a user