-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
299 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=objectpools/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.Extensions.ObjectPool; | ||
|
||
namespace MzLibUtil; | ||
|
||
// Used to pool HashSet instances to reduce memory allocations | ||
public class DictionaryPool<TKey, TValue> where TKey : notnull | ||
{ | ||
private readonly ObjectPool<Dictionary<TKey, TValue>> _pool; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="DictionaryPool{TKey, TValue}"/> class. | ||
/// </summary> | ||
/// <param name="initialCapacity">Initial capacity for the pooled Dictionary instances.</param> | ||
public DictionaryPool(int initialCapacity = 16) | ||
{ | ||
var policy = new DictionaryPooledObjectPolicy<TKey, TValue>(initialCapacity); | ||
var provider = new DefaultObjectPoolProvider { MaximumRetained = Environment.ProcessorCount * 2 }; | ||
_pool = provider.Create(policy); | ||
} | ||
|
||
/// <summary> | ||
/// Retrieves a Dictionary instance from the pool. | ||
/// </summary> | ||
/// <returns>A Dictionary instance.</returns> | ||
public Dictionary<TKey, TValue> Get() => _pool.Get(); | ||
|
||
/// <summary> | ||
/// Returns a Dictionary instance back to the pool. | ||
/// </summary> | ||
/// <param name="dictionary">The Dictionary instance to return.</param> | ||
public void Return(Dictionary<TKey, TValue> dictionary) | ||
{ | ||
if (dictionary == null) throw new ArgumentNullException(nameof(dictionary)); | ||
dictionary.Clear(); // Ensure the Dictionary is clean before returning it to the pool | ||
_pool.Return(dictionary); | ||
} | ||
|
||
private class DictionaryPooledObjectPolicy<TKeyItem, TValueItem>(int initialCapacity) | ||
: PooledObjectPolicy<Dictionary<TKeyItem, TValueItem>> | ||
where TKeyItem : notnull | ||
{ | ||
private int InitialCapacity { get; } = initialCapacity; | ||
|
||
public override Dictionary<TKeyItem, TValueItem> Create() | ||
{ | ||
return new Dictionary<TKeyItem, TValueItem>(capacity: InitialCapacity); | ||
} | ||
|
||
public override bool Return(Dictionary<TKeyItem, TValueItem> obj) | ||
{ | ||
// Ensure the Dictionary can be safely reused | ||
obj.Clear(); | ||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.Extensions.ObjectPool; | ||
|
||
namespace MzLibUtil; | ||
|
||
// Example Usage: | ||
// var pool = new HashSetPool<int>(); | ||
// var hashSet = pool.Get(); | ||
// hashSet.Add(1); | ||
// Do Work | ||
// pool.Return(hashSet); | ||
|
||
// Used to pool HashSet instances to reduce memory allocations | ||
public class HashSetPool<T> | ||
{ | ||
private readonly ObjectPool<HashSet<T>> _pool; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="HashSetPool{T}"/> class. | ||
/// </summary> | ||
/// <param name="initialCapacity">Initial capacity for the pooled HashSet instances.</param> | ||
public HashSetPool(int initialCapacity = 16) | ||
{ | ||
var policy = new HashSetPooledObjectPolicy<T>(initialCapacity); | ||
_pool = new DefaultObjectPool<HashSet<T>>(policy); | ||
} | ||
|
||
/// <summary> | ||
/// Retrieves a HashSet instance from the pool. | ||
/// </summary> | ||
/// <returns>A HashSet instance.</returns> | ||
public HashSet<T> Get() => _pool.Get(); | ||
|
||
/// <summary> | ||
/// Returns a HashSet instance back to the pool. | ||
/// </summary> | ||
/// <param name="hashSet">The HashSet instance to return.</param> | ||
public void Return(HashSet<T> hashSet) | ||
{ | ||
if (hashSet == null) throw new ArgumentNullException(nameof(hashSet)); | ||
hashSet.Clear(); // Ensure the HashSet is clean before returning it to the pool | ||
_pool.Return(hashSet); | ||
} | ||
|
||
private class HashSetPooledObjectPolicy<TItem>(int initialCapacity) : PooledObjectPolicy<HashSet<TItem>> | ||
{ | ||
public override HashSet<TItem> Create() | ||
{ | ||
return new HashSet<TItem>(capacity: initialCapacity); | ||
} | ||
|
||
public override bool Return(HashSet<TItem> obj) | ||
{ | ||
// Ensure the HashSet can be safely reused | ||
obj.Clear(); | ||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.Extensions.ObjectPool; | ||
|
||
namespace MzLibUtil; | ||
|
||
// Used to pool HashSet instances to reduce memory allocations | ||
public class ListPool<T> | ||
{ | ||
private readonly ObjectPool<List<T>> _pool; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="ListPool{T}"/> class. | ||
/// </summary> | ||
/// <param name="initialCapacity">Initial capacity for the pooled HashSet instances.</param> | ||
public ListPool(int initialCapacity = 16) | ||
{ | ||
var policy = new ListPooledObjectPolicy<T>(initialCapacity); | ||
var provider = new DefaultObjectPoolProvider { MaximumRetained = Environment.ProcessorCount * 2 }; | ||
_pool = provider.Create(policy); | ||
} | ||
|
||
/// <summary> | ||
/// Retrieves a HashSet instance from the pool. | ||
/// </summary> | ||
/// <returns>A HashSet instance.</returns> | ||
public List<T> Get() => _pool.Get(); | ||
|
||
/// <summary> | ||
/// Returns a HashSet instance back to the pool. | ||
/// </summary> | ||
/// <param name="list">The HashSet instance to return.</param> | ||
public void Return(List<T> list) | ||
{ | ||
if (list == null) throw new ArgumentNullException(nameof(list)); | ||
list.Clear(); // Ensure the HashSet is clean before returning it to the pool | ||
_pool.Return(list); | ||
} | ||
|
||
private class ListPooledObjectPolicy<TItem>(int initialCapacity) : PooledObjectPolicy<List<TItem>> | ||
{ | ||
private int InitialCapacity { get; } = initialCapacity; | ||
|
||
public override List<TItem> Create() | ||
{ | ||
return new List<TItem>(capacity: InitialCapacity); | ||
} | ||
|
||
public override bool Return(List<TItem> obj) | ||
{ | ||
// Ensure the HashSet can be safely reused | ||
obj.Clear(); | ||
return true; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
using MzLibUtil; | ||
using NUnit.Framework; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.CodeAnalysis; | ||
|
||
namespace Test; | ||
|
||
[TestFixture] | ||
[ExcludeFromCodeCoverage] | ||
public class HashSetPoolTests | ||
{ | ||
[Test] | ||
public void Get_ReturnsHashSetInstance() | ||
{ | ||
var pool = new HashSetPool<int>(); | ||
var hashSet = pool.Get(); | ||
Assert.That(hashSet, Is.Not.Null); | ||
pool.Return(hashSet); | ||
} | ||
|
||
[Test] | ||
public void Return_ClearsHashSetBeforeReturningToPool() | ||
{ | ||
var pool = new HashSetPool<int>(); | ||
var hashSet = pool.Get(); | ||
hashSet.Add(1); | ||
pool.Return(hashSet); | ||
Assert.That(hashSet.Count, Is.EqualTo(0)); | ||
} | ||
|
||
[Test] | ||
public void Return_ThrowsArgumentNullException_WhenHashSetIsNull() | ||
{ | ||
var pool = new HashSetPool<int>(); | ||
Assert.Throws<ArgumentNullException>(() => pool.Return(null)); | ||
} | ||
} | ||
|
||
[TestFixture] | ||
[ExcludeFromCodeCoverage] | ||
public class DictionaryPoolTests | ||
{ | ||
[Test] | ||
public void Get_ReturnsDictionaryInstance() | ||
{ | ||
var dictionaryPool = new DictionaryPool<string, int>(); | ||
var dictionary = dictionaryPool.Get(); | ||
Assert.That(dictionary, Is.Not.Null); | ||
Assert.That(dictionary, Is.InstanceOf<Dictionary<string, int>>()); | ||
} | ||
|
||
[Test] | ||
public void Return_ClearsAndReturnsDictionaryToPool() | ||
{ | ||
var dictionaryPool = new DictionaryPool<string, int>(); | ||
var dictionary = dictionaryPool.Get(); | ||
dictionary["key"] = 42; | ||
|
||
dictionaryPool.Return(dictionary); | ||
|
||
Assert.That(dictionary.Count, Is.EqualTo(0)); | ||
} | ||
|
||
[Test] | ||
public void Return_ThrowsArgumentNullException_WhenDictionaryIsNull() | ||
{ | ||
var dictionaryPool = new DictionaryPool<string, int>(); | ||
Assert.Throws<ArgumentNullException>(() => dictionaryPool.Return(null)); | ||
} | ||
} | ||
|
||
[TestFixture] | ||
[ExcludeFromCodeCoverage] | ||
public class ListPoolTests | ||
{ | ||
[Test] | ||
public void ListPool_Get_ReturnsListWithInitialCapacity() | ||
{ | ||
// Arrange | ||
int initialCapacity = 16; | ||
var listPool = new ListPool<int>(initialCapacity); | ||
|
||
// Act | ||
var list = listPool.Get(); | ||
|
||
// Assert | ||
Assert.That(list, Is.Not.Null); | ||
Assert.That(list.Capacity, Is.EqualTo(initialCapacity)); | ||
} | ||
|
||
[Test] | ||
public void ListPool_Return_ClearsListBeforeReturningToPool() | ||
{ | ||
// Arrange | ||
var listPool = new ListPool<int>(); | ||
var list = listPool.Get(); | ||
list.Add(1); | ||
list.Add(2); | ||
|
||
// Act | ||
listPool.Return(list); | ||
var returnedList = listPool.Get(); | ||
|
||
// Assert | ||
Assert.That(returnedList, Is.Not.Null); | ||
Assert.That(returnedList, Is.Empty); | ||
} | ||
|
||
[Test] | ||
public void ListPool_Return_ThrowsArgumentNullException_WhenListIsNull() | ||
{ | ||
// Arrange | ||
var listPool = new ListPool<int>(); | ||
|
||
// Act & Assert | ||
Assert.That(() => listPool.Return(null), Throws.ArgumentNullException); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters