Skip to content
This repository was archived by the owner on Dec 19, 2018. It is now read-only.

Commit e568e43

Browse files
committed
Add ObjectPool<StringBuilder> to default services
- can now use pooled `StringBuilder`s to address aspnet/HttpAbstractions#561 and similar issues nit: Fix incomplete test noted when adding new one
1 parent f76fb06 commit e568e43

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

src/Microsoft.AspNetCore.Hosting/WebHostBuilder.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics;
77
using System.IO;
88
using System.Reflection;
9+
using System.Text;
910
using Microsoft.AspNetCore.Builder;
1011
using Microsoft.AspNetCore.Hosting.Builder;
1112
using Microsoft.AspNetCore.Hosting.Internal;
@@ -17,6 +18,7 @@
1718
using Microsoft.Extensions.DependencyInjection;
1819
using Microsoft.Extensions.DependencyInjection.Extensions;
1920
using Microsoft.Extensions.Logging;
21+
using Microsoft.Extensions.ObjectPool;
2022
using Microsoft.Extensions.PlatformAbstractions;
2123

2224
namespace Microsoft.AspNetCore.Hosting
@@ -26,6 +28,11 @@ namespace Microsoft.AspNetCore.Hosting
2628
/// </summary>
2729
public class WebHostBuilder : IWebHostBuilder
2830
{
31+
// StringBuilderPooledObjectPolicy.MaximumRetainedCapacity's default is too small for general use and will
32+
// cause useful StringBuilders to be thrown away in common scenarios e.g. serializing an antiforgery cookie.
33+
// Instead of that value (4 kB), allow the few StringBuilders to grow to 1 MB.
34+
private const int MaximumBuilderSize = 0x100000;
35+
2936
private readonly IHostingEnvironment _hostingEnvironment;
3037
private readonly ILoggerFactory _loggerFactory;
3138
private readonly List<Action<IServiceCollection>> _configureServicesDelegates;
@@ -135,7 +142,7 @@ public IWebHostBuilder Configure(Action<IApplicationBuilder> configureApp)
135142
}
136143

137144
/// <summary>
138-
/// Configure the provided <see cref="ILoggerFactory"/> which will be available as a hosting service.
145+
/// Configure the provided <see cref="ILoggerFactory"/> which will be available as a hosting service.
139146
/// </summary>
140147
/// <param name="configureLogging">The delegate that configures the <see cref="ILoggerFactory"/>.</param>
141148
/// <returns>The <see cref="IWebHostBuilder"/>.</returns>
@@ -155,7 +162,7 @@ public IWebHost Build()
155162

156163
var appEnvironment = hostingContainer.GetRequiredService<IApplicationEnvironment>();
157164
var startupLoader = hostingContainer.GetRequiredService<IStartupLoader>();
158-
165+
159166
var contentRootPath = ResolveContentRootPath(_options.ContentRootPath, appEnvironment.ApplicationBasePath);
160167
var applicationName = ResolveApplicationName() ?? appEnvironment.ApplicationName;
161168

@@ -198,6 +205,17 @@ private IServiceCollection BuildHostingServices()
198205
services.AddSingleton<DiagnosticSource>(diagnosticSource);
199206
services.AddSingleton<DiagnosticListener>(diagnosticSource);
200207

208+
services.AddSingleton<ObjectPool<StringBuilder>>(serviceProvider =>
209+
{
210+
var provider = new DefaultObjectPoolProvider();
211+
var policy = new StringBuilderPooledObjectPolicy
212+
{
213+
MaximumRetainedCapacity = MaximumBuilderSize,
214+
};
215+
216+
return provider.Create(policy);
217+
});
218+
201219
// Conjure up a RequestServices
202220
services.AddTransient<IStartupFilter, AutoRequestServicesStartupFilter>();
203221

src/Microsoft.AspNetCore.Hosting/project.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
"Microsoft.AspNetCore.Hosting.Server.Abstractions": "1.0.0-*",
1919
"Microsoft.AspNetCore.Http": "1.0.0-*",
2020
"Microsoft.AspNetCore.Http.Extensions": "1.0.0-*",
21-
"Microsoft.Extensions.FileProviders.Physical": "1.0.0-*",
22-
"Microsoft.Extensions.Options": "1.0.0-*",
2321
"Microsoft.Extensions.Configuration": "1.0.0-*",
2422
"Microsoft.Extensions.Configuration.CommandLine": "1.0.0-*",
2523
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-*",
2624
"Microsoft.Extensions.Configuration.Json": "1.0.0-*",
2725
"Microsoft.Extensions.DependencyInjection": "1.0.0-*",
26+
"Microsoft.Extensions.FileProviders.Physical": "1.0.0-*",
2827
"Microsoft.Extensions.Logging": "1.0.0-*",
28+
"Microsoft.Extensions.ObjectPool": "1.0.0-*",
29+
"Microsoft.Extensions.Options": "1.0.0-*",
2930
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-*",
3031
"Microsoft.Extensions.TypeNameHelper.Sources": {
3132
"version": "1.0.0-*",

test/Microsoft.AspNetCore.Hosting.Tests/WebHostBuilderTests.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.IO;
7+
using System.Text;
78
using System.Threading.Tasks;
89
using Microsoft.AspNetCore.Hosting.Fakes;
910
using Microsoft.AspNetCore.Hosting.Internal;
@@ -13,8 +14,8 @@
1314
using Microsoft.AspNetCore.Http.Internal;
1415
using Microsoft.Extensions.Configuration;
1516
using Microsoft.Extensions.DependencyInjection;
17+
using Microsoft.Extensions.ObjectPool;
1618
using Microsoft.Extensions.PlatformAbstractions;
17-
using System.Reflection;
1819
using Xunit;
1920

2021
namespace Microsoft.AspNetCore.Hosting
@@ -92,8 +93,27 @@ public async Task IApplicationLifetimeRegisteredEvenWhenStartupCtorThrows_Fallba
9293
using (host)
9394
{
9495
host.Start();
95-
var service = host.Services.GetServices<IApplicationLifetime>();
96-
Assert.NotNull(service);
96+
var services = host.Services.GetServices<IApplicationLifetime>();
97+
Assert.NotNull(services);
98+
Assert.NotEmpty(services);
99+
100+
await AssertResponseContains(server.RequestDelegate, "Exception from constructor");
101+
}
102+
}
103+
104+
[Fact]
105+
public async Task ObjectPoolOfStringBuilderRegistered_EvenWhenStartupCtorThrows()
106+
{
107+
var builder = CreateWebHostBuilder();
108+
var server = new TestServer();
109+
var host = builder.UseServer(server).UseStartup<StartupCtorThrows>().Build();
110+
using (host)
111+
{
112+
host.Start();
113+
var services = host.Services.GetServices<ObjectPool<StringBuilder>>();
114+
Assert.NotNull(services);
115+
Assert.NotEmpty(services);
116+
97117
await AssertResponseContains(server.RequestDelegate, "Exception from constructor");
98118
}
99119
}

0 commit comments

Comments
 (0)