Improves performance and reduce allocations in DefaultEndpointDataSource (#882)

This commit is contained in:
Gert Driesen 2018-10-22 23:20:15 +02:00 committed by James Newton-King
parent 4943bc4896
commit 26e5ea3274
2 changed files with 64 additions and 5 deletions

View File

@ -14,15 +14,20 @@ namespace Microsoft.AspNetCore.Routing
/// </summary>
public sealed class DefaultEndpointDataSource : EndpointDataSource
{
private readonly List<Endpoint> _endpoints;
private readonly IReadOnlyList<Endpoint> _endpoints;
/// <summary>
/// Initializes a new instance of the <see cref="DefaultEndpointDataSource" /> class.
/// </summary>
/// <param name="endpoints">The <see cref="Endpoint"/> instances that the data source will return.</param>
public DefaultEndpointDataSource(params Endpoint[] endpoints)
: this((IEnumerable<Endpoint>) endpoints)
{
if (endpoints == null)
{
throw new ArgumentNullException(nameof(endpoints));
}
_endpoints = (Endpoint[])endpoints.Clone();
}
/// <summary>
@ -36,8 +41,7 @@ namespace Microsoft.AspNetCore.Routing
throw new ArgumentNullException(nameof(endpoints));
}
_endpoints = new List<Endpoint>();
_endpoints.AddRange(endpoints);
_endpoints = new List<Endpoint>(endpoints);
}
/// <summary>

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Http;
using Xunit;
@ -26,6 +25,34 @@ namespace Microsoft.AspNetCore.Routing
endpoint => Assert.Equal("2", endpoint.DisplayName));
}
[Fact]
public void Constructor_Params_ShouldMakeCopyOfEndpoints()
{
// Arrange
var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "1");
var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "2");
var endpoints = new[] { endpoint1, endpoint2 };
// Act
var dataSource = new DefaultEndpointDataSource(endpoints);
Array.Resize(ref endpoints, 1);
endpoints[0] = null;
// Assert
Assert.Equal(2, dataSource.Endpoints.Count);
Assert.Contains(endpoint1, dataSource.Endpoints);
Assert.Contains(endpoint2, dataSource.Endpoints);
}
[Fact]
public void Constructor_Params_ShouldThrowArgumentNullExceptionWhenEndpointsIsNull()
{
Endpoint[] endpoints = null;
var actual = Assert.Throws<ArgumentNullException>(() => new DefaultEndpointDataSource(endpoints));
Assert.Equal("endpoints", actual.ParamName);
}
[Fact]
public void Constructor_Enumerable_EndpointsInitialized()
{
@ -41,5 +68,33 @@ namespace Microsoft.AspNetCore.Routing
endpoint => Assert.Equal("1", endpoint.DisplayName),
endpoint => Assert.Equal("2", endpoint.DisplayName));
}
[Fact]
public void Constructor_Enumerable_ShouldMakeCopyOfEndpoints()
{
// Arrange
var endpoint1 = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "1");
var endpoint2 = new Endpoint(TestConstants.EmptyRequestDelegate, EndpointMetadataCollection.Empty, "2");
var endpoints = new List<Endpoint> { endpoint1, endpoint2 };
// Act
var dataSource = new DefaultEndpointDataSource((IEnumerable<Endpoint>)endpoints);
endpoints.RemoveAt(0);
endpoints[0] = null;
// Assert
Assert.Equal(2, dataSource.Endpoints.Count);
Assert.Contains(endpoint1, dataSource.Endpoints);
Assert.Contains(endpoint2, dataSource.Endpoints);
}
[Fact]
public void Constructor_Enumerable_ShouldThrowArgumentNullExceptionWhenEndpointsIsNull()
{
IEnumerable<Endpoint> endpoints = null;
var actual = Assert.Throws<ArgumentNullException>(() => new DefaultEndpointDataSource(endpoints));
Assert.Equal("endpoints", actual.ParamName);
}
}
}