Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce ObjectPool and use it for ResilienceContext pooling #1111

Merged
merged 6 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions src/Polly.Core.Benchmarks/README.md
martincostello marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,44 @@ LaunchCount=2 WarmupCount=10

## PIPELINES

| Method | Components | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------- |----------- |------------:|----------:|----------:|------:|--------:|-------:|----------:|------------:|
| ExecutePipeline_V7 | 1 | 71.29 ns | 1.309 ns | 1.959 ns | 1.00 | 0.00 | 0.0362 | 304 B | 1.00 |
| ExecutePipeline_V8 | 1 | 92.93 ns | 1.398 ns | 2.049 ns | 1.30 | 0.05 | 0.0181 | 152 B | 0.50 |
| | | | | | | | | | |
| ExecutePipeline_V7 | 2 | 164.39 ns | 5.294 ns | 7.592 ns | 1.00 | 0.00 | 0.0658 | 552 B | 1.00 |
| ExecutePipeline_V8 | 2 | 126.74 ns | 1.198 ns | 1.755 ns | 0.77 | 0.04 | 0.0181 | 152 B | 0.28 |
| | | | | | | | | | |
| ExecutePipeline_V7 | 5 | 540.07 ns | 16.941 ns | 24.832 ns | 1.00 | 0.00 | 0.1545 | 1296 B | 1.00 |
| ExecutePipeline_V8 | 5 | 257.13 ns | 2.748 ns | 4.114 ns | 0.48 | 0.03 | 0.0181 | 152 B | 0.12 |
| | | | | | | | | | |
| ExecutePipeline_V7 | 10 | 1,111.72 ns | 16.405 ns | 23.527 ns | 1.00 | 0.00 | 0.3014 | 2536 B | 1.00 |
| ExecutePipeline_V8 | 10 | 467.93 ns | 6.546 ns | 9.388 ns | 0.42 | 0.01 | 0.0181 | 152 B | 0.06 |
| Method | Components | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------- |----------- |------------:|----------:|-----------:|------------:|------:|--------:|-------:|----------:|------------:|
| ExecutePipeline_V7 | 1 | 74.78 ns | 1.555 ns | 2.279 ns | 75.63 ns | 1.00 | 0.00 | 0.0362 | 304 B | 1.00 |
| ExecutePipeline_V8 | 1 | 85.69 ns | 0.500 ns | 0.732 ns | 85.36 ns | 1.15 | 0.04 | - | - | 0.00 |
| | | | | | | | | | | |
| ExecutePipeline_V7 | 2 | 165.37 ns | 1.157 ns | 1.732 ns | 165.59 ns | 1.00 | 0.00 | 0.0658 | 552 B | 1.00 |
| ExecutePipeline_V8 | 2 | 119.10 ns | 0.653 ns | 0.915 ns | 119.63 ns | 0.72 | 0.01 | - | - | 0.00 |
| | | | | | | | | | | |
| ExecutePipeline_V7 | 5 | 533.97 ns | 7.327 ns | 10.967 ns | 536.79 ns | 1.00 | 0.00 | 0.1545 | 1296 B | 1.00 |
| ExecutePipeline_V8 | 5 | 227.69 ns | 1.236 ns | 1.812 ns | 227.72 ns | 0.43 | 0.01 | - | - | 0.00 |
| | | | | | | | | | | |
| ExecutePipeline_V7 | 10 | 1,191.41 ns | 35.512 ns | 53.152 ns | 1,192.79 ns | 1.00 | 0.00 | 0.3014 | 2536 B | 1.00 |
| ExecutePipeline_V8 | 10 | 557.95 ns | 76.434 ns | 112.036 ns | 505.58 ns | 0.47 | 0.09 | - | - | 0.00 |

## TIMEOUT

| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------ |---------:|--------:|---------:|------:|--------:|-------:|----------:|------------:|
| ExecuteTimeout_V7 | 287.1 ns | 9.20 ns | 12.59 ns | 1.00 | 0.00 | 0.0868 | 728 B | 1.00 |
| ExecuteTimeout_V8 | 272.9 ns | 3.16 ns | 4.54 ns | 0.95 | 0.04 | 0.0439 | 368 B | 0.51 |
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------ |---------:|--------:|--------:|------:|--------:|-------:|----------:|------------:|
| ExecuteTimeout_V7 | 281.5 ns | 5.76 ns | 8.08 ns | 1.00 | 0.00 | 0.0868 | 728 B | 1.00 |
| ExecuteTimeout_V8 | 268.9 ns | 3.86 ns | 5.53 ns | 0.96 | 0.04 | 0.0257 | 216 B | 0.30 |

## RETRY

| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---------------- |---------:|--------:|--------:|------:|--------:|-------:|----------:|------------:|
| ExecuteRetry_V7 | 162.5 ns | 2.33 ns | 3.34 ns | 1.00 | 0.00 | 0.0687 | 576 B | 1.00 |
| ExecuteRetry_V8 | 152.3 ns | 1.31 ns | 1.93 ns | 0.94 | 0.02 | 0.0181 | 152 B | 0.26 |
| ExecuteRetry_V7 | 169.8 ns | 4.98 ns | 6.98 ns | 1.00 | 0.00 | 0.0687 | 576 B | 1.00 |
| ExecuteRetry_V8 | 144.9 ns | 2.35 ns | 3.52 ns | 0.85 | 0.04 | - | - | 0.00 |

## RATE LIMITER

| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---------------------- |---------:|--------:|--------:|------:|--------:|-------:|----------:|------------:|
| ExecuteRateLimiter_V7 | 173.8 ns | 2.33 ns | 3.48 ns | 1.00 | 0.00 | 0.0448 | 376 B | 1.00 |
| ExecuteRateLimiter_V8 | 207.9 ns | 2.06 ns | 2.89 ns | 1.19 | 0.03 | 0.0229 | 192 B | 0.51 |
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|---------------------- |---------:|---------:|---------:|------:|--------:|-------:|----------:|------------:|
| ExecuteRateLimiter_V7 | 190.8 ns | 10.01 ns | 14.98 ns | 1.00 | 0.00 | 0.0448 | 376 B | 1.00 |
| ExecuteRateLimiter_V8 | 199.6 ns | 2.54 ns | 3.64 ns | 1.05 | 0.09 | 0.0048 | 40 B | 0.11 |

## STRATEGY PIPELINE (TIMEOUT + RETRY + TIMEOUT + RATE LIMITER)

| Method | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|--------------------------- |---------:|----------:|----------:|---------:|------:|--------:|-------:|----------:|------------:|
| ExecuteStrategyPipeline_V7 | 1.207 us | 0.0201 us | 0.0295 us | 1.202 us | 1.00 | 0.00 | 0.2861 | 2400 B | 1.00 |
| ExecuteStrategyPipeline_V8 | 1.117 us | 0.0297 us | 0.0407 us | 1.118 us | 0.93 | 0.05 | 0.0935 | 792 B | 0.33 |
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|--------------------------- |---------:|----------:|----------:|------:|--------:|-------:|----------:|------------:|
| ExecuteStrategyPipeline_V7 | 1.321 us | 0.0355 us | 0.0520 us | 1.00 | 0.00 | 0.2861 | 2400 B | 1.00 |
| ExecuteStrategyPipeline_V8 | 1.126 us | 0.0193 us | 0.0283 us | 0.85 | 0.03 | 0.0763 | 640 B | 0.27 |
4 changes: 2 additions & 2 deletions src/Polly.Core.Tests/ExecutionRejectedExceptionTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace Polly.Core.Tests.Timeout;
namespace Polly.Core.Tests;

public class ExecutionRejectedExceptionTests
{
[Fact]
public void Ctor_Ok()
{
new CustomException().Message.Should().Be("Exception of type 'Polly.Core.Tests.Timeout.ExecutionRejectedExceptionTests+CustomException' was thrown.");
new CustomException().Message.Should().Be("Exception of type 'Polly.Core.Tests.ExecutionRejectedExceptionTests+CustomException' was thrown.");
new CustomException("Dummy").Message.Should().Be("Dummy");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

using System;

namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

/// <summary>
/// Utility that serializes and deserializes the exceptions using the binary formatter.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Moq;
using Polly.Utils;

namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

internal class FakeTimeProvider : Mock<TimeProvider>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Polly.Strategy;

namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

public class TestArguments : IResilienceArguments
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

public class TestResilienceStrategy : ResilienceStrategy
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

#pragma warning disable CA1031 // Do not catch general exception types

Expand Down
2 changes: 1 addition & 1 deletion src/Polly.Core.Tests/Polly.Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
</ItemGroup>

<ItemGroup>
<Using Include="Polly.Core.Tests.Utils" />
<Using Include="Polly.Core.Tests.Helpers" />
</ItemGroup>
</Project>
3 changes: 0 additions & 3 deletions src/Polly.Core.Tests/Registry/StrategyId.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;

namespace Polly.Core.Tests.Registry;

public record StrategyId(Type Type, string BuilderName, string InstanceName = "")
Expand Down
10 changes: 10 additions & 0 deletions src/Polly.Core.Tests/ResilienceContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ public void Get_EnsureDefaults()
AssertDefaults(context);
}

[Fact]
public void Get_EnsurePooled()
{
var context = ResilienceContext.Get();

ResilienceContext.Return(context);

ResilienceContext.Get().Should().BeSameAs(context);
}

[Fact]
public void Return_Null_Throws()
{
Expand Down
3 changes: 0 additions & 3 deletions src/Polly.Core.Tests/Retry/RetryDelayGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using System;
using System.Threading.Tasks;
using Polly.Retry;
using Polly.Strategy;
using Xunit;

namespace Polly.Core.Tests.Retry;

Expand Down
1 change: 0 additions & 1 deletion src/Polly.Core.Tests/Retry/RetryHelperTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using Polly.Retry;

namespace Polly.Core.Tests.Retry;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.ComponentModel.DataAnnotations;
using Polly.Builder;
using Polly.Retry;
using Xunit;

namespace Polly.Core.Tests.Retry;

Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Core.Tests/Strategy/OutcomeEventTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;
using System.Threading.Tasks;
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;
Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Core.Tests/Strategy/OutcomeGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;
using System.Threading.Tasks;
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;
Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Core.Tests/Strategy/OutcomePredicateTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;
using System.Threading.Tasks;
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;
Expand Down
1 change: 0 additions & 1 deletion src/Polly.Core.Tests/Strategy/OutcomeTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;
Expand Down
6 changes: 3 additions & 3 deletions src/Polly.Core.Tests/Strategy/SimpleEventTests.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using Polly.Strategy;

namespace Polly.Core.Tests.Timeout;
namespace Polly.Core.Tests.Strategy;

public class SimpleEventTests
{
[Fact]
public async Task Add_EnsureOrdering()
{
var ev = new DummyEvent();
List<int> raisedEvents = new List<int>();
var raisedEvents = new List<int>();

ev.Add(() => raisedEvents.Add(1));
ev.Add(args => raisedEvents.Add(2));
Expand Down Expand Up @@ -41,7 +41,7 @@ public async Task CreateHandler_Ok(int count)
var ev = new DummyEvent();
var events = new List<int>();

for (int i = 0; i < count; i++)
for (var i = 0; i < count; i++)
{
ev.Add(() => events.Add(i));
}
Expand Down
1 change: 0 additions & 1 deletion src/Polly.Core.Tests/Timeout/TimeoutAttributeTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.ComponentModel.DataAnnotations;
using Polly.Timeout;

namespace Polly.Core.Tests.Timeout;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.ComponentModel.DataAnnotations;
using Polly.Timeout;
using Polly.Utils;
using Xunit;

namespace Polly.Core.Tests.Timeout;

Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Core.Tests/Timeout/TimeoutUtilTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using Polly.Timeout;
using Xunit;

namespace Polly.Core.Tests.Timeout;
public class TimeoutUtilTests
Expand Down
111 changes: 111 additions & 0 deletions src/Polly.Core.Tests/Utils/ObjectPoolTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using Polly.Utils;

namespace Polly.Core.Tests.Utils;

public class ObjectPoolTests
{
[Fact]
public void GetAnd_ReturnObject_SameInstance()
{
// Arrange
var pool = new ObjectPool<object>(() => new object(), _ => true);

var obj1 = pool.Get();
pool.Return(obj1);

// Act
var obj2 = pool.Get();

// Assert
Assert.Same(obj1, obj2);
}

[Fact]
public void MaxCapacity_Ok()
{
ObjectPool<object>.MaxCapacity.Should().Be((Environment.ProcessorCount * 2) - 1);
}

[Fact]
public void MaxCapacity_Respected()
{
// Arrange
var pool = new ObjectPool<object>(() => new object(), _ => true);
var items1 = GetStoreReturn(pool);

// Act
var items2 = GetStoreReturn(pool);

// Assert
items1.Should().BeEquivalentTo(items2);
}

[Fact]
public void MaxCapacityOverflow_Respected()
{
// Arrange
var count = ObjectPool<object>.MaxCapacity + 10;
var pool = new ObjectPool<object>(() => new object(), _ => true);
var items1 = GetStoreReturn(pool, count);

// Act
var items2 = GetStoreReturn(pool, count);

// Assert
items1.Last().Should().NotBeSameAs(items2.Last());
}

[Fact]
public void CreatedByPolicy()
{
// Arrange
var policy = new ListPolicy();
var pool = new ObjectPool<List<int>>(ListPolicy.Create, ListPolicy.Return);

// Act
var list = pool.Get();

// Assert
Assert.Equal(17, list.Capacity);
}

[Fact]
public void Return_RejectedByPolicy()
{
// Arrange
var policy = new ListPolicy();
var pool = new ObjectPool<List<int>>(ListPolicy.Create, ListPolicy.Return);
var list1 = pool.Get();
list1.Capacity = 20;

// Act
pool.Return(list1);
var list2 = pool.Get();

// Assert
Assert.NotSame(list1, list2);
}

private static List<object> GetStoreReturn(ObjectPool<object> pool, int? count = null)
{
var items = new List<object>();
for (int i = 0; i < (count ?? ObjectPool<object>.MaxCapacity); i++)
{
items.Add(pool.Get());
}

foreach (var item in items)
{
pool.Return(item);
}

return items;
}

private class ListPolicy
{
public static List<int> Create() => new(17);

public static bool Return(List<int> obj) => obj.Capacity == 17;
}
}
1 change: 0 additions & 1 deletion src/Polly.Core.Tests/Utils/TimeSpanAttributeTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.ComponentModel.DataAnnotations;

namespace Polly.Core.Tests.Utils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Polly.Core.Tests.Utils;

public class ValidationContextExtensions
public class ValidationContextExtensionsTests
{
[Fact]
public void GetMemberName_Ok()
Expand Down
Loading