@@ -41,11 +41,10 @@ internal enum RouteType
4141internal sealed class MyTcpSessionClientBase : TcpSessionClient
4242{
4343 #region Paths
44- public static ReadOnlySpan < byte > Json => "/json"u8 ;
45- public static ReadOnlySpan < byte > Plaintext => "/plaintext"u8 ;
44+ private static ReadOnlySpan < byte > Json => "/json"u8 ;
45+ private static ReadOnlySpan < byte > Plaintext => "/plaintext"u8 ;
4646 #endregion
4747
48-
4948 private static ReadOnlySpan < byte > PlainTextBody => "Hello, World!"u8 ;
5049 private static ReadOnlySpan < byte > JsonBody => "{\" message\" :\" Hello, World!\" }"u8 ;
5150
@@ -68,14 +67,30 @@ protected override async Task ReceiveLoopAsync(ITransport transport)
6867
6968 while ( true )
7069 {
71- var readResult = await pipeReader . ReadAsync ( ) ;
70+ ValueTask < ReadResult > readTask = pipeReader . ReadAsync ( ) ;
71+ ReadResult readResult ;
72+
73+ if ( readTask . IsCompleted )
74+ {
75+ readResult = readTask . Result ;
76+ }
77+ else
78+ {
79+ readResult = await readTask . ConfigureAwait ( false ) ;
80+ }
81+
7282 var bufferSequence = readResult . Buffer ;
7383
7484 var totalConsumed = ProcessRequests ( bufferSequence , pipeWriter , out var responseCount ) ;
7585
7686 if ( responseCount > 0 )
7787 {
78- await pipeWriter . FlushAsync ( ) ;
88+ ValueTask < FlushResult > flushTask = pipeWriter . FlushAsync ( ) ;
89+
90+ if ( ! flushTask . IsCompleted )
91+ {
92+ await flushTask . ConfigureAwait ( false ) ;
93+ }
7994 }
8095
8196 if ( totalConsumed > 0 )
@@ -94,7 +109,7 @@ protected override async Task ReceiveLoopAsync(ITransport transport)
94109 }
95110 }
96111
97- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
112+ [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
98113 private static long ProcessRequests ( ReadOnlySequence < byte > buffer , PipeWriter writer , out int responseCount )
99114 {
100115 var seqReader = new SequenceReader < byte > ( buffer ) ;
@@ -105,23 +120,20 @@ private static long ProcessRequests(ReadOnlySequence<byte> buffer, PipeWriter wr
105120 {
106121 var startConsumed = seqReader . Consumed ;
107122
108- // 请求行
109123 if ( ! TryReadLine ( ref seqReader , out var requestLineLength ) )
110124 {
111- // 请求行不完整,不消费任何数据
112125 break ;
113126 }
114127
115128 var requestLineConsumed = requestLineLength + 2 ;
116129
117- // 读取Headers,直到空行;若不完整,回退并等待更多数据
118130 var headersStartConsumed = seqReader . Consumed ;
119131 bool headersComplete = false ;
132+
120133 while ( ! seqReader . End )
121134 {
122135 if ( ! TryReadLine ( ref seqReader , out var headerLength ) )
123136 {
124- // 回退到读取Headers前的位置,等待更多数据
125137 var rewind = seqReader . Consumed - headersStartConsumed ;
126138 if ( rewind > 0 )
127139 {
@@ -134,163 +146,118 @@ private static long ProcessRequests(ReadOnlySequence<byte> buffer, PipeWriter wr
134146 if ( headerLength == 0 )
135147 {
136148 headersComplete = true ;
137- break ; // headers 结束
149+ break ;
138150 }
139151 }
140152
141153 if ( ! headersComplete )
142154 {
143- // 不完整,等待更多数据
144155 break ;
145156 }
146157
147- // 解析URL - 直接在原始位置解析,避免Slice
148158 var routeType = ParseUrlFast ( buffer . Slice ( startConsumed ) , requestLineConsumed ) ;
149159
150- // 计算本次消费的字节数
151160 var consumed = seqReader . Consumed - startConsumed ;
152161 totalConsumed += consumed ;
153162
154- // 写入响应
155163 WriteResponseSync ( writer , routeType ) ;
156164 responseCount ++ ;
157165 }
158166
159167 return totalConsumed ;
160168 }
161169
162- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
170+ [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
163171 private static void WriteResponseSync ( PipeWriter writer , RouteType routeType )
164172 {
165- switch ( routeType )
173+ if ( routeType == RouteType . Plaintext )
166174 {
167- case RouteType . Plaintext :
168- writer . Write ( PlaintextPreamble ) ;
169- writer . Write ( DateHeader . HeaderBytes ) ;
170- writer . Write ( PlainTextBody ) ;
171- break ;
172- case RouteType . Json :
173- writer . Write ( JsonPreamble ) ;
174- writer . Write ( DateHeader . HeaderBytes ) ;
175- writer . Write ( JsonBody ) ;
176- break ;
175+ writer . Write ( PlaintextPreamble ) ;
176+ writer . Write ( DateHeader . HeaderBytes ) ;
177+ writer . Write ( PlainTextBody ) ;
178+ }
179+ else if ( routeType == RouteType . Json )
180+ {
181+ writer . Write ( JsonPreamble ) ;
182+ writer . Write ( DateHeader . HeaderBytes ) ;
183+ writer . Write ( JsonBody ) ;
177184 }
178185 }
179186
180- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
187+ [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
181188 private static bool TryReadLine ( ref SequenceReader < byte > reader , out long length )
182189 {
183- var start = reader . Consumed ;
184-
185- while ( ! reader . End )
190+ if ( reader . TryAdvanceTo ( ( byte ) '\r ' , advancePastDelimiter : false ) )
186191 {
187- if ( reader . TryRead ( out var b ) )
192+ var start = reader . Consumed ;
193+
194+ if ( ! reader . TryPeek ( 1 , out var next ) )
188195 {
189- if ( b == '\r ' )
190- {
191- // 查看是否有'\n',若暂不可用则回退并判定不完整
192- if ( ! reader . TryPeek ( out var next ) )
193- {
194- // 回退已读取的'\r'
195- reader . Rewind ( 1 ) ;
196- length = 0 ;
197- return false ;
198- }
199- if ( next == '\n ' )
200- {
201- // 消费'\n'并返回本行长度(不含CRLF)
202- reader . Advance ( 1 ) ;
203- length = reader . Consumed - start - 2 ;
204- return true ;
205- }
206- }
196+ length = 0 ;
197+ return false ;
207198 }
199+
200+ if ( next == '\n ' )
201+ {
202+ var lineLength = reader . Consumed ;
203+ reader . Advance ( 2 ) ;
204+ length = lineLength - start ;
205+ return true ;
206+ }
207+
208+ reader . Advance ( 1 ) ;
209+ return TryReadLine ( ref reader , out length ) ;
208210 }
209211
210212 length = 0 ;
211213 return false ;
212214 }
213215
214- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
216+ [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
215217 private static RouteType ParseUrlFast ( ReadOnlySequence < byte > sequence , long requestLineLength )
216218 {
217219 var reader = new SequenceReader < byte > ( sequence ) ;
218220
219- // 跳过方法
220- var spaceCount = 0 ;
221- var urlStart = 0L ;
222- var urlEnd = 0L ;
223-
224- while ( reader . Consumed < requestLineLength && ! reader . End )
221+ if ( ! reader . TryAdvanceTo ( ( byte ) ' ' , advancePastDelimiter : true ) )
225222 {
226- if ( reader . TryRead ( out var b ) )
227- {
228- if ( b == ' ' )
229- {
230- spaceCount ++ ;
231- if ( spaceCount == 1 )
232- {
233- urlStart = reader . Consumed ;
234- }
235- else if ( spaceCount == 2 )
236- {
237- urlEnd = reader . Consumed - 1 ;
238- break ;
239- }
240- }
241- }
223+ return RouteType . Unknown ;
242224 }
243225
244- if ( spaceCount < 2 )
226+ var urlStart = reader . Consumed ;
227+
228+ if ( ! reader . TryAdvanceTo ( ( byte ) ' ' , advancePastDelimiter : false ) )
245229 {
246230 return RouteType . Unknown ;
247231 }
248232
249- var urlLength = urlEnd - urlStart ;
233+ var urlLength = reader . Consumed - urlStart ;
250234
251- // 截取URL片段
252- var startPos = sequence . GetPosition ( urlStart ) ;
253- var urlSlice = sequence . Slice ( startPos , urlLength ) ;
254-
255- // "/plaintext"
256235 if ( urlLength == Plaintext . Length )
257236 {
237+ var urlSlice = sequence . Slice ( urlStart , urlLength ) ;
238+
258239 if ( urlSlice . IsSingleSegment )
259240 {
260- if ( urlSlice . FirstSpan . SequenceEqual ( Plaintext ) )
261- {
262- return RouteType . Plaintext ;
263- }
264- }
265- else
266- {
267- Span < byte > tmp = stackalloc byte [ ( int ) urlLength ] ;
268- urlSlice . CopyTo ( tmp ) ;
269- if ( tmp . SequenceEqual ( Plaintext ) )
270- {
271- return RouteType . Plaintext ;
272- }
241+ return urlSlice . FirstSpan . SequenceEqual ( Plaintext ) ? RouteType . Plaintext : RouteType . Unknown ;
273242 }
243+
244+ Span < byte > tmp = stackalloc byte [ ( int ) urlLength ] ;
245+ urlSlice . CopyTo ( tmp ) ;
246+ return tmp . SequenceEqual ( Plaintext ) ? RouteType . Plaintext : RouteType . Unknown ;
274247 }
275- // "/json"
276- else if ( urlLength == Json . Length )
248+
249+ if ( urlLength == Json . Length )
277250 {
251+ var urlSlice = sequence . Slice ( urlStart , urlLength ) ;
252+
278253 if ( urlSlice . IsSingleSegment )
279254 {
280- if ( urlSlice . FirstSpan . SequenceEqual ( Json ) )
281- {
282- return RouteType . Json ;
283- }
284- }
285- else
286- {
287- Span < byte > tmp = stackalloc byte [ ( int ) urlLength ] ;
288- urlSlice . CopyTo ( tmp ) ;
289- if ( tmp . SequenceEqual ( Json ) )
290- {
291- return RouteType . Json ;
292- }
255+ return urlSlice . FirstSpan . SequenceEqual ( Json ) ? RouteType . Json : RouteType . Unknown ;
293256 }
257+
258+ Span < byte > tmp = stackalloc byte [ ( int ) urlLength ] ;
259+ urlSlice . CopyTo ( tmp ) ;
260+ return tmp . SequenceEqual ( Json ) ? RouteType . Json : RouteType . Unknown ;
294261 }
295262
296263 return RouteType . Unknown ;
0 commit comments