@@ -14,10 +14,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
14
14
{
15
15
public class SocketOutput : ISocketOutput
16
16
{
17
+ public const int MaxPooledWriteReqs = 1024 ;
18
+
17
19
private const int _maxPendingWrites = 3 ;
18
20
private const int _maxBytesPreCompleted = 65536 ;
19
21
private const int _initialTaskQueues = 64 ;
20
- private const int _maxPooledWriteContexts = 32 ;
21
22
22
23
private static WaitCallback _returnBlocks = ( state ) => ReturnBlocks ( ( MemoryPoolBlock2 ) state ) ;
23
24
@@ -39,7 +40,6 @@ public class SocketOutput : ISocketOutput
39
40
40
41
// This locks access to to all of the below fields
41
42
private readonly object _contextLock = new object ( ) ;
42
- private bool _isDisposed = false ;
43
43
44
44
// The number of write operations that have been scheduled so far
45
45
// but have not completed.
@@ -50,7 +50,7 @@ public class SocketOutput : ISocketOutput
50
50
private WriteContext _nextWriteContext ;
51
51
private readonly Queue < TaskCompletionSource < object > > _tasksPending ;
52
52
private readonly Queue < TaskCompletionSource < object > > _tasksCompleted ;
53
- private readonly Queue < WriteContext > _writeContextPool ;
53
+ private readonly Queue < UvWriteReq > _writeReqPool ;
54
54
55
55
public SocketOutput (
56
56
KestrelThread thread ,
@@ -59,7 +59,8 @@ public SocketOutput(
59
59
Connection connection ,
60
60
long connectionId ,
61
61
IKestrelTrace log ,
62
- IThreadPool threadPool )
62
+ IThreadPool threadPool ,
63
+ Queue < UvWriteReq > writeReqPool )
63
64
{
64
65
_thread = thread ;
65
66
_socket = socket ;
@@ -69,7 +70,7 @@ public SocketOutput(
69
70
_threadPool = threadPool ;
70
71
_tasksPending = new Queue < TaskCompletionSource < object > > ( _initialTaskQueues ) ;
71
72
_tasksCompleted = new Queue < TaskCompletionSource < object > > ( _initialTaskQueues ) ;
72
- _writeContextPool = new Queue < WriteContext > ( _maxPooledWriteContexts ) ;
73
+ _writeReqPool = writeReqPool ;
73
74
74
75
_head = memory . Lease ( ) ;
75
76
_tail = _head ;
@@ -96,14 +97,7 @@ public Task WriteAsync(
96
97
{
97
98
if ( _nextWriteContext == null )
98
99
{
99
- if ( _writeContextPool . Count > 0 )
100
- {
101
- _nextWriteContext = _writeContextPool . Dequeue ( ) ;
102
- }
103
- else
104
- {
105
- _nextWriteContext = new WriteContext ( this ) ;
106
- }
100
+ _nextWriteContext = new WriteContext ( this ) ;
107
101
}
108
102
109
103
if ( socketShutdownSend )
@@ -304,7 +298,6 @@ private void OnWriteCompleted(WriteContext writeContext)
304
298
305
299
lock ( _contextLock )
306
300
{
307
- PoolWriteContext ( writeContext ) ;
308
301
if ( _nextWriteContext != null )
309
302
{
310
303
scheduleWrite = true ;
@@ -382,32 +375,6 @@ private void ReturnAllBlocks()
382
375
}
383
376
}
384
377
385
- private void PoolWriteContext ( WriteContext writeContext )
386
- {
387
- // called inside _contextLock
388
- if ( ! _isDisposed && _writeContextPool . Count < _maxPooledWriteContexts )
389
- {
390
- writeContext . Reset ( ) ;
391
- _writeContextPool . Enqueue ( writeContext ) ;
392
- }
393
- else
394
- {
395
- writeContext . Dispose ( ) ;
396
- }
397
- }
398
-
399
- private void Dispose ( )
400
- {
401
- lock ( _contextLock )
402
- {
403
- _isDisposed = true ;
404
- while ( _writeContextPool . Count > 0 )
405
- {
406
- _writeContextPool . Dequeue ( ) . Dispose ( ) ;
407
- }
408
- }
409
- }
410
-
411
378
void ISocketOutput . Write ( ArraySegment < byte > buffer , bool immediate )
412
379
{
413
380
var task = WriteAsync ( buffer , immediate ) ;
@@ -449,7 +416,7 @@ private static void BytesBetween(MemoryPoolIterator2 start, MemoryPoolIterator2
449
416
buffers ++ ;
450
417
}
451
418
452
- private class WriteContext : IDisposable
419
+ private class WriteContext
453
420
{
454
421
private static WaitCallback _returnWrittenBlocks = ( state ) => ReturnWrittenBlocks ( ( MemoryPoolBlock2 ) state ) ;
455
422
@@ -473,8 +440,6 @@ private class WriteContext : IDisposable
473
440
public WriteContext ( SocketOutput self )
474
441
{
475
442
Self = self ;
476
- _writeReq = new UvWriteReq ( Self . _log ) ;
477
- _writeReq . Init ( Self . _thread . Loop ) ;
478
443
}
479
444
480
445
/// <summary>
@@ -495,13 +460,24 @@ public void DoWriteIfNeeded()
495
460
var lockedEndBlock = _lockedEnd . Block ;
496
461
var lockedEndIndex = _lockedEnd . Index ;
497
462
463
+ if ( Self . _writeReqPool . Count > 0 )
464
+ {
465
+ _writeReq = Self . _writeReqPool . Dequeue ( ) ;
466
+ }
467
+ else
468
+ {
469
+ _writeReq = new UvWriteReq ( Self . _log ) ;
470
+ _writeReq . Init ( Self . _thread . Loop ) ;
471
+ }
472
+
498
473
_writeReq . Write ( Self . _socket , _lockedStart , _lockedEnd , _bufferCount , ( _writeReq , status , error , state ) =>
499
474
{
500
- var _this = ( WriteContext ) state ;
501
- _this . ScheduleReturnFullyWrittenBlocks ( ) ;
502
- _this . WriteStatus = status ;
503
- _this . WriteError = error ;
504
- _this . DoShutdownIfNeeded ( ) ;
475
+ var writeContext = ( WriteContext ) state ;
476
+ writeContext . PoolWriteReq ( writeContext . _writeReq ) ;
477
+ writeContext . ScheduleReturnFullyWrittenBlocks ( ) ;
478
+ writeContext . WriteStatus = status ;
479
+ writeContext . WriteError = error ;
480
+ writeContext . DoShutdownIfNeeded ( ) ;
505
481
} , this ) ;
506
482
507
483
Self . _head = lockedEndBlock ;
@@ -545,14 +521,12 @@ public void DoDisconnectIfNeeded()
545
521
}
546
522
else if ( Self . _socket . IsClosed )
547
523
{
548
- Self . Dispose ( ) ;
549
524
Complete ( ) ;
550
525
return ;
551
526
}
552
527
553
528
Self . _socket . Dispose ( ) ;
554
529
Self . ReturnAllBlocks ( ) ;
555
- Self . Dispose ( ) ;
556
530
Self . _log . ConnectionStop ( Self . _connectionId ) ;
557
531
Complete ( ) ;
558
532
}
@@ -561,7 +535,19 @@ public void Complete()
561
535
{
562
536
Self . OnWriteCompleted ( this ) ;
563
537
}
564
-
538
+
539
+ private void PoolWriteReq ( UvWriteReq writeReq )
540
+ {
541
+ if ( Self . _writeReqPool . Count < MaxPooledWriteReqs )
542
+ {
543
+ Self . _writeReqPool . Enqueue ( writeReq ) ;
544
+ }
545
+ else
546
+ {
547
+ writeReq . Dispose ( ) ;
548
+ }
549
+ }
550
+
565
551
private void ScheduleReturnFullyWrittenBlocks ( )
566
552
{
567
553
var block = _lockedStart . Block ;
@@ -608,29 +594,8 @@ private void LockWrite()
608
594
609
595
_lockedStart = new MemoryPoolIterator2 ( head , head . Start ) ;
610
596
_lockedEnd = new MemoryPoolIterator2 ( tail , tail . End ) ;
611
-
612
- BytesBetween ( _lockedStart , _lockedEnd , out ByteCount , out _bufferCount ) ;
613
- }
614
597
615
- public void Reset ( )
616
- {
617
- _lockedStart = default ( MemoryPoolIterator2 ) ;
618
- _lockedEnd = default ( MemoryPoolIterator2 ) ;
619
- _bufferCount = 0 ;
620
- ByteCount = 0 ;
621
-
622
- SocketShutdownSend = false ;
623
- SocketDisconnect = false ;
624
-
625
- WriteStatus = 0 ;
626
- WriteError = null ;
627
-
628
- ShutdownSendStatus = 0 ;
629
- }
630
-
631
- public void Dispose ( )
632
- {
633
- _writeReq . Dispose ( ) ;
598
+ BytesBetween ( _lockedStart , _lockedEnd , out ByteCount , out _bufferCount ) ;
634
599
}
635
600
}
636
601
}
0 commit comments