Skip to content

Commit 648217f

Browse files
committed
Pool http context
1 parent a263612 commit 648217f

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

src/Benchmarks/Startup.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Data.Common;
67
using System.Data.SqlClient;
78
using Benchmarks.Data;
89
using Microsoft.AspNetCore.Builder;
910
using Microsoft.AspNetCore.Hosting;
1011
using Microsoft.AspNetCore.Http;
12+
using Microsoft.AspNetCore.Http.Features;
13+
using Microsoft.AspNetCore.Http.Internal;
1114
using Microsoft.EntityFrameworkCore;
1215
using Microsoft.Extensions.Configuration;
1316
using Microsoft.Extensions.DependencyInjection;
@@ -43,6 +46,7 @@ public void ConfigureServices(IServiceCollection services)
4346
// No scenarios covered by the benchmarks require the HttpContextAccessor so we're replacing it with a
4447
// no-op version to avoid the cost.
4548
services.AddSingleton(typeof(IHttpContextAccessor), typeof(InertHttpContextAccessor));
49+
services.AddSingleton(typeof(IHttpContextFactory), typeof(PooledContextFactory));
4650

4751
if (Scenarios.Any("Db"))
4852
{
@@ -161,5 +165,69 @@ public HttpContext HttpContext
161165
set { return; }
162166
}
163167
}
168+
169+
public class PooledContextFactory : IHttpContextFactory
170+
{
171+
private IHttpContextAccessor _httpContextAccessor;
172+
173+
[ThreadStatic]
174+
static Queue<DefaultHttpContext> _contextPool;
175+
176+
public PooledContextFactory() : this(httpContextAccessor: null)
177+
{
178+
}
179+
180+
public PooledContextFactory(IHttpContextAccessor httpContextAccessor)
181+
{
182+
_httpContextAccessor = httpContextAccessor;
183+
}
184+
185+
private Queue<DefaultHttpContext> ContextPool
186+
{
187+
get
188+
{
189+
if (_contextPool == null)
190+
{
191+
_contextPool = new Queue<DefaultHttpContext>(16);
192+
}
193+
194+
return _contextPool;
195+
}
196+
}
197+
198+
public HttpContext Create(IFeatureCollection featureCollection)
199+
{
200+
var contextPool = ContextPool;
201+
if (contextPool.Count > 0)
202+
{
203+
var context = contextPool.Dequeue();
204+
context.Initialize(featureCollection);
205+
return context;
206+
}
207+
208+
return new DefaultHttpContext(featureCollection);
209+
}
210+
211+
public void Dispose(HttpContext httpContext)
212+
{
213+
if (_httpContextAccessor != null)
214+
{
215+
_httpContextAccessor.HttpContext = null;
216+
}
217+
218+
var context = httpContext as DefaultHttpContext;
219+
220+
if (context != null)
221+
{
222+
context.Uninitialize();
223+
224+
var contextPool = ContextPool;
225+
if (contextPool.Count < 16)
226+
{
227+
contextPool.Enqueue(context);
228+
}
229+
}
230+
}
231+
}
164232
}
165233
}

0 commit comments

Comments
 (0)