diff --git a/src/Microsoft.AspNet.Hosting.Server.Abstractions/IServerFactory.cs b/src/Microsoft.AspNet.Hosting.Server.Abstractions/IServerFactory.cs index ff188af7..a8cc68f3 100644 --- a/src/Microsoft.AspNet.Hosting.Server.Abstractions/IServerFactory.cs +++ b/src/Microsoft.AspNet.Hosting.Server.Abstractions/IServerFactory.cs @@ -11,6 +11,6 @@ namespace Microsoft.AspNet.Hosting.Server public interface IServerFactory { IFeatureCollection Initialize(IConfiguration configuration); - IDisposable Start(IFeatureCollection serverFeatures, Func application); + IDisposable Start(IFeatureCollection serverFeatures, Func> application); } } diff --git a/src/Microsoft.AspNet.Hosting/Builder/HttpContextFactory.cs b/src/Microsoft.AspNet.Hosting/Builder/HttpContextFactory.cs index 7fccad68..c74adbef 100644 --- a/src/Microsoft.AspNet.Hosting/Builder/HttpContextFactory.cs +++ b/src/Microsoft.AspNet.Hosting/Builder/HttpContextFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Collections.Concurrent; using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Features; using Microsoft.AspNet.Http.Internal; @@ -9,9 +11,47 @@ namespace Microsoft.AspNet.Hosting.Builder { public class HttpContextFactory : IHttpContextFactory { + private static int _capacity = 32 * Environment.ProcessorCount; + private static readonly ConcurrentQueue _contextPool = new ConcurrentQueue(); + private static readonly ConcurrentQueue _featureCollectionPool = new ConcurrentQueue(); + public HttpContext CreateHttpContext(IFeatureCollection featureCollection) { - return new DefaultHttpContext(new FeatureCollection(featureCollection)); + DefaultHttpContext context; + if (_contextPool.TryDequeue(out context)) + { + context.Initalize(CreateFeatureCollection(featureCollection)); + return context; + } + return new DefaultHttpContext(CreateFeatureCollection(featureCollection), PoolContext); + } + + internal FeatureCollection CreateFeatureCollection(IFeatureCollection innerFeatureCollection) + { + FeatureCollection featureCollection; + if (_featureCollectionPool.TryDequeue(out featureCollection)) + { + featureCollection.Reset(innerFeatureCollection); + return featureCollection; + } + return new FeatureCollection(innerFeatureCollection, PoolFeatureCollection); + } + + internal void PoolContext(DefaultHttpContext context) + { + // Benign race condition + if (_contextPool.Count < _capacity) + { + _contextPool.Enqueue(context); + } + } + internal void PoolFeatureCollection(FeatureCollection context) + { + // Benign race condition + if (_featureCollectionPool.Count < _capacity) + { + _featureCollectionPool.Enqueue(context); + } } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Hosting/Internal/HostingEngine.cs b/src/Microsoft.AspNet.Hosting/Internal/HostingEngine.cs index d072b362..5d3b7f5a 100644 --- a/src/Microsoft.AspNet.Hosting/Internal/HostingEngine.cs +++ b/src/Microsoft.AspNet.Hosting/Internal/HostingEngine.cs @@ -71,6 +71,7 @@ public virtual IDisposable Start() async features => { var httpContext = contextFactory.CreateHttpContext(features); + httpContext.ApplicationServices = _applicationServices; var requestIdentifier = GetRequestIdentifier(httpContext); @@ -79,6 +80,8 @@ public virtual IDisposable Start() contextAccessor.HttpContext = httpContext; await application(httpContext); } + + return httpContext; }); _applicationLifetime.NotifyStarted(); diff --git a/src/Microsoft.AspNet.Hosting/project.json b/src/Microsoft.AspNet.Hosting/project.json index ad736ead..762642d7 100644 --- a/src/Microsoft.AspNet.Hosting/project.json +++ b/src/Microsoft.AspNet.Hosting/project.json @@ -26,7 +26,8 @@ "dnx451": { }, "dnxcore50": { "dependencies": { - "System.Console": "4.0.0-beta-*" + "System.Console": "4.0.0-beta-*", + "System.Collections.Concurrent": "4.0.11-beta-*" } } }