11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4- using System ;
54using System . Buffers ;
6- using System . Buffers . Binary ;
75using System . Diagnostics ;
8- using System . IO ;
96using System . IO . Pipelines ;
10- using System . Linq ;
117using System . Net . Http . HPack ;
12- using System . Threading . Tasks ;
138using BenchmarkDotNet . Attributes ;
149using Microsoft . AspNetCore . Http ;
1510using Microsoft . AspNetCore . Http . Features ;
1611using Microsoft . AspNetCore . Server . Kestrel . Core ;
17- using Microsoft . AspNetCore . Server . Kestrel . Core . Internal ;
1812using Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Http ;
1913using Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Http2 ;
20- using Microsoft . AspNetCore . Server . Kestrel . Core . Internal . Infrastructure ;
2114using Microsoft . AspNetCore . Testing ;
22- using Microsoft . Extensions . Logging . Abstractions ;
2315using Microsoft . Extensions . Primitives ;
2416using Microsoft . Net . Http . Headers ;
2517using Http2HeadersEnumerator = Microsoft . AspNetCore . Server . Kestrel . Core . Tests . Http2HeadersEnumerator ;
@@ -36,15 +28,20 @@ public abstract class Http2ConnectionBenchmarkBase
3628 private int _currentStreamId ;
3729 private byte [ ] _headersBuffer ;
3830 private DuplexPipe . DuplexPipePair _connectionPair ;
39- private Http2Frame _httpFrame ;
4031 private int _dataWritten ;
32+ private Task _requestProcessingTask ;
33+
34+ private readonly Http2Frame _receiveHttpFrame = new ( ) ;
35+ private readonly Http2Frame _sendHttpFrame = new ( ) ;
4136
4237 protected abstract Task ProcessRequest ( HttpContext httpContext ) ;
4338
39+ [ Params ( 0 , 1 , 3 ) ]
40+ public int NumCookies { get ; set ; }
41+
4442 public virtual void GlobalSetup ( )
4543 {
4644 _memoryPool = PinnedBlockMemoryPoolFactory . Create ( ) ;
47- _httpFrame = new Http2Frame ( ) ;
4845
4946 var options = new PipeOptions ( _memoryPool , readerScheduler : PipeScheduler . Inline , writerScheduler : PipeScheduler . Inline , useSynchronizationContext : false ) ;
5047
@@ -56,6 +53,16 @@ public virtual void GlobalSetup()
5653 _httpRequestHeaders [ HeaderNames . Scheme ] = new StringValues ( "http" ) ;
5754 _httpRequestHeaders [ HeaderNames . Authority ] = new StringValues ( "localhost:80" ) ;
5855
56+ if ( NumCookies > 0 )
57+ {
58+ var cookies = new string [ NumCookies ] ;
59+ for ( var index = 0 ; index < NumCookies ; index ++ )
60+ {
61+ cookies [ index ] = $ "{ index } ={ index + 1 } ";
62+ }
63+ _httpRequestHeaders [ HeaderNames . Cookie ] = cookies ;
64+ }
65+
5966 _headersBuffer = new byte [ 1024 * 16 ] ;
6067 _hpackEncoder = new DynamicHPackEncoder ( ) ;
6168
@@ -79,7 +86,7 @@ public virtual void GlobalSetup()
7986
8087 _currentStreamId = 1 ;
8188
82- _ = _connection . ProcessRequestsAsync ( new DummyApplication ( ProcessRequest , new MockHttpContextFactory ( ) ) ) ;
89+ _requestProcessingTask = _connection . ProcessRequestsAsync ( new DummyApplication ( ProcessRequest , new MockHttpContextFactory ( ) ) ) ;
8390
8491 _connectionPair . Application . Output . Write ( Http2Connection . ClientPreface ) ;
8592 _connectionPair . Application . Output . WriteSettings ( new Http2PeerSettings
@@ -89,45 +96,45 @@ public virtual void GlobalSetup()
8996 _connectionPair . Application . Output . FlushAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
9097
9198 // Read past connection setup frames
92- ReceiveFrameAsync ( _connectionPair . Application . Input , _httpFrame ) . GetAwaiter ( ) . GetResult ( ) ;
93- Debug . Assert ( _httpFrame . Type == Http2FrameType . SETTINGS ) ;
94- ReceiveFrameAsync ( _connectionPair . Application . Input , _httpFrame ) . GetAwaiter ( ) . GetResult ( ) ;
95- Debug . Assert ( _httpFrame . Type == Http2FrameType . WINDOW_UPDATE ) ;
96- ReceiveFrameAsync ( _connectionPair . Application . Input , _httpFrame ) . GetAwaiter ( ) . GetResult ( ) ;
97- Debug . Assert ( _httpFrame . Type == Http2FrameType . SETTINGS ) ;
99+ ReceiveFrameAsync ( _connectionPair . Application . Input ) . GetAwaiter ( ) . GetResult ( ) ;
100+ Debug . Assert ( _receiveHttpFrame . Type == Http2FrameType . SETTINGS ) ;
101+ ReceiveFrameAsync ( _connectionPair . Application . Input ) . GetAwaiter ( ) . GetResult ( ) ;
102+ Debug . Assert ( _receiveHttpFrame . Type == Http2FrameType . WINDOW_UPDATE ) ;
103+ ReceiveFrameAsync ( _connectionPair . Application . Input ) . GetAwaiter ( ) . GetResult ( ) ;
104+ Debug . Assert ( _receiveHttpFrame . Type == Http2FrameType . SETTINGS ) ;
98105 }
99106
100107 [ Benchmark ]
101108 public async Task MakeRequest ( )
102109 {
103110 _requestHeadersEnumerator . Initialize ( _httpRequestHeaders ) ;
104111 _requestHeadersEnumerator . MoveNext ( ) ;
105- _connectionPair . Application . Output . WriteStartStream ( streamId : _currentStreamId , _hpackEncoder , _requestHeadersEnumerator , _headersBuffer , endStream : true , frame : _httpFrame ) ;
112+ _connectionPair . Application . Output . WriteStartStream ( streamId : _currentStreamId , _hpackEncoder , _requestHeadersEnumerator , _headersBuffer , endStream : true , frame : _sendHttpFrame ) ;
106113 await _connectionPair . Application . Output . FlushAsync ( ) ;
107114
108115 while ( true )
109116 {
110- await ReceiveFrameAsync ( _connectionPair . Application . Input , _httpFrame ) ;
117+ await ReceiveFrameAsync ( _connectionPair . Application . Input ) ;
111118
112- if ( _httpFrame . StreamId != _currentStreamId && _httpFrame . StreamId != 0 )
119+ if ( _receiveHttpFrame . StreamId != _currentStreamId && _receiveHttpFrame . StreamId != 0 )
113120 {
114- throw new Exception ( $ "Unexpected stream ID: { _httpFrame . StreamId } ") ;
121+ throw new Exception ( $ "Unexpected stream ID: { _receiveHttpFrame . StreamId } ") ;
115122 }
116123
117- if ( _httpFrame . Type == Http2FrameType . DATA )
124+ if ( _receiveHttpFrame . Type == Http2FrameType . DATA )
118125 {
119- _dataWritten += _httpFrame . DataPayloadLength ;
126+ _dataWritten += _receiveHttpFrame . DataPayloadLength ;
120127 }
121128
122129 if ( _dataWritten > 1024 * 32 )
123130 {
124- _connectionPair . Application . Output . WriteWindowUpdateAsync ( streamId : 0 , _dataWritten , _httpFrame ) ;
131+ _connectionPair . Application . Output . WriteWindowUpdateAsync ( streamId : 0 , _dataWritten , _sendHttpFrame ) ;
125132 await _connectionPair . Application . Output . FlushAsync ( ) ;
126133
127134 _dataWritten = 0 ;
128135 }
129136
130- if ( ( _httpFrame . HeadersFlags & Http2HeadersFrameFlags . END_STREAM ) == Http2HeadersFrameFlags . END_STREAM )
137+ if ( ( _receiveHttpFrame . HeadersFlags & Http2HeadersFrameFlags . END_STREAM ) == Http2HeadersFrameFlags . END_STREAM )
131138 {
132139 break ;
133140 }
@@ -136,7 +143,7 @@ public async Task MakeRequest()
136143 _currentStreamId += 2 ;
137144 }
138145
139- internal async ValueTask ReceiveFrameAsync ( PipeReader pipeReader , Http2Frame frame , uint maxFrameSize = Http2PeerSettings . DefaultMaxFrameSize )
146+ internal async ValueTask ReceiveFrameAsync ( PipeReader pipeReader , uint maxFrameSize = Http2PeerSettings . DefaultMaxFrameSize )
140147 {
141148 while ( true )
142149 {
@@ -147,7 +154,7 @@ internal async ValueTask ReceiveFrameAsync(PipeReader pipeReader, Http2Frame fra
147154
148155 try
149156 {
150- if ( Http2FrameReader . TryReadFrame ( ref buffer , frame , maxFrameSize , out var framePayload ) )
157+ if ( Http2FrameReader . TryReadFrame ( ref buffer , _receiveHttpFrame , maxFrameSize , out var framePayload ) )
151158 {
152159 consumed = examined = framePayload . End ;
153160 return ;
@@ -170,9 +177,10 @@ internal async ValueTask ReceiveFrameAsync(PipeReader pipeReader, Http2Frame fra
170177 }
171178
172179 [ GlobalCleanup ]
173- public void Dispose ( )
180+ public async ValueTask DisposeAsync ( )
174181 {
175182 _connectionPair . Application . Output . Complete ( ) ;
183+ await _requestProcessingTask ;
176184 _memoryPool ? . Dispose ( ) ;
177185 }
178186}
0 commit comments