Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit b3382f5

Browse files
committed
Unify memorypool use
1 parent edfce36 commit b3382f5

File tree

10 files changed

+504
-345
lines changed

10 files changed

+504
-345
lines changed

src/Microsoft.AspNet.Server.Kestrel/Http/Frame.FeatureCollection.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,15 +291,7 @@ async Task<Stream> IHttpUpgradeFeature.UpgradeAsync()
291291
}
292292
}
293293

294-
var memoryBlock = Memory2.Lease();
295-
try
296-
{
297-
await ProduceStartAndFireOnStarting(memoryBlock, immediate: true);
298-
}
299-
finally
300-
{
301-
Memory2.Return(memoryBlock);
302-
}
294+
await ProduceStartAndFireOnStarting(immediate: true);
303295

304296
return DuplexStream;
305297
}

src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs

Lines changed: 119 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,11 @@ public async Task RequestProcessingAsync()
272272

273273
HttpContextFactory.Dispose(httpContext);
274274

275+
await ProduceEnd();
276+
275277
var memoryBlock = Memory2.Lease();
276278
try
277279
{
278-
await ProduceEnd(memoryBlock);
279280

280281
var segment = memoryBlock.Data;
281282
while (await RequestBody.ReadAsync(segment.Array, segment.Offset, segment.Count) != 0)
@@ -393,43 +394,19 @@ private async Task FireOnCompleted()
393394

394395
public void Flush()
395396
{
396-
var memoryBlock = Memory2.Lease();
397-
try
398-
{
399-
ProduceStartAndFireOnStarting(memoryBlock, immediate: false).GetAwaiter().GetResult();
400-
}
401-
finally
402-
{
403-
Memory2.Return(memoryBlock);
404-
}
397+
ProduceStartAndFireOnStarting(immediate: false).GetAwaiter().GetResult();
405398
SocketOutput.Write(_emptyData, immediate: true);
406399
}
407400

408401
public async Task FlushAsync(CancellationToken cancellationToken)
409402
{
410-
var memoryBlock = Memory2.Lease();
411-
try
412-
{
413-
await ProduceStartAndFireOnStarting(memoryBlock, immediate: false);
414-
}
415-
finally
416-
{
417-
Memory2.Return(memoryBlock);
418-
}
403+
await ProduceStartAndFireOnStarting(immediate: false);
419404
await SocketOutput.WriteAsync(_emptyData, immediate: true, cancellationToken: cancellationToken);
420405
}
421406

422407
public void Write(ArraySegment<byte> data)
423408
{
424-
var memoryBlock = Memory2.Lease();
425-
try
426-
{
427-
ProduceStartAndFireOnStarting(memoryBlock, immediate: false).GetAwaiter().GetResult();
428-
}
429-
finally
430-
{
431-
Memory2.Return(memoryBlock);
432-
}
409+
ProduceStartAndFireOnStarting(immediate: false).GetAwaiter().GetResult();
433410

434411
if (_autoChunk)
435412
{
@@ -447,15 +424,7 @@ public void Write(ArraySegment<byte> data)
447424

448425
public async Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationToken)
449426
{
450-
var memoryBlock = Memory2.Lease();
451-
try
452-
{
453-
await ProduceStartAndFireOnStarting(memoryBlock, immediate: false);
454-
}
455-
finally
456-
{
457-
Memory2.Return(memoryBlock);
458-
}
427+
await ProduceStartAndFireOnStarting(immediate: false);
459428

460429
if (_autoChunk)
461430
{
@@ -538,7 +507,7 @@ public void ProduceContinue()
538507
}
539508
}
540509

541-
public async Task ProduceStartAndFireOnStarting(MemoryPoolBlock2 memoryBlock, bool immediate = true)
510+
public async Task ProduceStartAndFireOnStarting(bool immediate = true)
542511
{
543512
if (_responseStarted) return;
544513

@@ -551,11 +520,10 @@ public async Task ProduceStartAndFireOnStarting(MemoryPoolBlock2 memoryBlock, bo
551520
_applicationException);
552521
}
553522

554-
await ProduceStart(memoryBlock, immediate, appCompleted: false);
523+
await ProduceStart(immediate, appCompleted: false);
555524
}
556525

557526
private Task ProduceStart(
558-
MemoryPoolBlock2 memoryBlock,
559527
bool immediate,
560528
bool appCompleted)
561529
{
@@ -564,10 +532,10 @@ private Task ProduceStart(
564532

565533
var statusBytes = ReasonPhrases.ToStatusBytes(StatusCode, ReasonPhrase);
566534

567-
return CreateResponseHeader(statusBytes, memoryBlock, appCompleted, immediate);
535+
return CreateResponseHeader(statusBytes, appCompleted, immediate);
568536
}
569537

570-
private async Task ProduceEnd(MemoryPoolBlock2 memoryBlock)
538+
private async Task ProduceEnd()
571539
{
572540
if (_applicationException != null)
573541
{
@@ -587,7 +555,7 @@ private async Task ProduceEnd(MemoryPoolBlock2 memoryBlock)
587555
}
588556
}
589557

590-
await ProduceStart(memoryBlock, immediate: true, appCompleted: true);
558+
await ProduceStart(immediate: true, appCompleted: true);
591559

592560
// _autoChunk should be checked after we are sure ProduceStart() has been called
593561
// since ProduceStart() may set _autoChunk to true.
@@ -602,12 +570,12 @@ private async Task ProduceEnd(MemoryPoolBlock2 memoryBlock)
602570
}
603571
}
604572

605-
private static void OutputAsciiBlock(string data, MemoryPoolBlock2 memoryBlock, ISocketOutput output)
573+
private static void OutputAsciiBlock(string data, ref MemoryPoolBlock2 currentMemoryBlock, MemoryPool2 memory, ISocketOutput output)
606574
{
607-
var start = memoryBlock.Start;
608-
var end = start + memoryBlock.Data.Count;
609-
var array = memoryBlock.Array;
610-
var current = memoryBlock.End;
575+
var start = currentMemoryBlock.Start;
576+
var end = start + currentMemoryBlock.Data.Count;
577+
var array = currentMemoryBlock.Array;
578+
var current = currentMemoryBlock.End;
611579

612580
foreach (var chr in data)
613581
{
@@ -617,22 +585,31 @@ private static void OutputAsciiBlock(string data, MemoryPoolBlock2 memoryBlock,
617585

618586
if (current == end)
619587
{
620-
output.Write(memoryBlock.Data, immediate: false);
588+
var socketOutput = output as SocketOutput;
589+
if (socketOutput != null)
590+
{
591+
socketOutput.WriteAsync(currentMemoryBlock, immediate: false);
592+
currentMemoryBlock = memory.Lease();
593+
}
594+
else
595+
{
596+
output.Write(currentMemoryBlock.Data, immediate: false);
597+
}
621598
current = start;
622599
}
623600
}
624-
memoryBlock.End = current;
601+
currentMemoryBlock.End = current;
625602
}
626603

627-
private static void OutputAsciiBlock(byte[] data, MemoryPoolBlock2 memoryBlock, ISocketOutput output)
604+
private static void OutputAsciiBlock(byte[] data, ref MemoryPoolBlock2 currentMemoryBlock, MemoryPool2 memory, ISocketOutput output)
628605
{
629606
var offset = 0;
630607
var remaining = data.Length;
631608

632-
var start = memoryBlock.Start;
633-
var end = start + memoryBlock.Data.Count;
634-
var array = memoryBlock.Array;
635-
var current = memoryBlock.End;
609+
var start = currentMemoryBlock.Start;
610+
var end = start + currentMemoryBlock.Data.Count;
611+
var array = currentMemoryBlock.Array;
612+
var current = currentMemoryBlock.End;
636613

637614
while (remaining > 0)
638615
{
@@ -646,97 +623,130 @@ private static void OutputAsciiBlock(byte[] data, MemoryPoolBlock2 memoryBlock,
646623

647624
if (current == end)
648625
{
649-
output.Write(memoryBlock.Data, immediate: false);
626+
var socketOutput = output as SocketOutput;
627+
if (socketOutput != null)
628+
{
629+
socketOutput.WriteAsync(currentMemoryBlock, immediate: false);
630+
currentMemoryBlock = memory.Lease();
631+
}
632+
else
633+
{
634+
output.Write(currentMemoryBlock.Data, immediate: false);
635+
}
650636
current = start;
651637
}
652638
}
653-
memoryBlock.End = current;
639+
currentMemoryBlock.End = current;
654640
}
655641

656642
private Task CreateResponseHeader(
657643
byte[] statusBytes,
658-
MemoryPoolBlock2 memoryBlock,
659644
bool appCompleted,
660645
bool immediate)
661646
{
662-
var blockRemaining = memoryBlock.Data.Count;
663647

664-
OutputAsciiBlock(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0, memoryBlock, SocketOutput);
648+
var memoryBlock = Memory2.Lease();
649+
try
650+
{
651+
var blockRemaining = memoryBlock.Data.Count;
665652

666-
OutputAsciiBlock(statusBytes, memoryBlock, SocketOutput);
653+
OutputAsciiBlock(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0, ref memoryBlock, Memory2, SocketOutput);
667654

668-
if (_responseHeaders.HasDefaultDate)
669-
{
670-
OutputAsciiBlock(_bytesDate, memoryBlock, SocketOutput);
671-
OutputAsciiBlock(DateHeaderValueManager.GetDateHeaderValueBytes(), memoryBlock, SocketOutput);
672-
OutputAsciiBlock(_bytesEndLine, memoryBlock, SocketOutput);
673-
}
655+
OutputAsciiBlock(statusBytes, ref memoryBlock, Memory2, SocketOutput);
674656

675-
foreach (var header in _responseHeaders.AsOutputEnumerable())
676-
{
677-
foreach (var value in header.Value)
657+
if (_responseHeaders.HasDefaultDate)
678658
{
679-
OutputAsciiBlock(header.Key, memoryBlock, SocketOutput);
680-
OutputAsciiBlock(value, memoryBlock, SocketOutput);
681-
OutputAsciiBlock(_bytesEndLine, memoryBlock, SocketOutput);
659+
OutputAsciiBlock(_bytesDate, ref memoryBlock, Memory2, SocketOutput);
660+
OutputAsciiBlock(DateHeaderValueManager.GetDateHeaderValueBytes(), ref memoryBlock, Memory2, SocketOutput);
661+
OutputAsciiBlock(_bytesEndLine, ref memoryBlock, Memory2, SocketOutput);
662+
}
682663

683-
if (_responseHeaders.HasConnection && value.IndexOf("close", StringComparison.OrdinalIgnoreCase) != -1)
664+
foreach (var header in _responseHeaders.AsOutputEnumerable())
665+
{
666+
foreach (var value in header.Value)
684667
{
685-
_keepAlive = false;
668+
OutputAsciiBlock(header.Key, ref memoryBlock, Memory2, SocketOutput);
669+
OutputAsciiBlock(value, ref memoryBlock, Memory2, SocketOutput);
670+
OutputAsciiBlock(_bytesEndLine, ref memoryBlock, Memory2, SocketOutput);
671+
672+
if (_responseHeaders.HasConnection && value.IndexOf("close", StringComparison.OrdinalIgnoreCase) != -1)
673+
{
674+
_keepAlive = false;
675+
}
686676
}
687677
}
688-
}
689-
690-
if (_responseHeaders.HasDefaultServer)
691-
{
692-
OutputAsciiBlock(_bytesServer, memoryBlock, SocketOutput);
693-
}
694678

695-
if (_keepAlive && !_responseHeaders.HasTransferEncoding && !_responseHeaders.HasContentLength)
696-
{
697-
if (appCompleted)
679+
if (_responseHeaders.HasDefaultServer)
698680
{
699-
// Don't set the Content-Length or Transfer-Encoding headers
700-
// automatically for HEAD requests or 101, 204, 205, 304 responses.
701-
if (Method != "HEAD" && StatusCanHaveBody(StatusCode))
702-
{
703-
// Since the app has completed and we are only now generating
704-
// the headers we can safely set the Content-Length to 0.
705-
OutputAsciiBlock(_bytesContentLengthZero, memoryBlock, SocketOutput);
706-
}
681+
OutputAsciiBlock(_bytesServer, ref memoryBlock, Memory2, SocketOutput);
707682
}
708-
else
683+
684+
if (_keepAlive && !_responseHeaders.HasTransferEncoding && !_responseHeaders.HasContentLength)
709685
{
710-
if (_httpVersion == HttpVersionType.Http1_1)
686+
if (appCompleted)
711687
{
712-
_autoChunk = true;
713-
OutputAsciiBlock(_bytesTransferEncodingChunked, memoryBlock, SocketOutput);
688+
// Don't set the Content-Length or Transfer-Encoding headers
689+
// automatically for HEAD requests or 101, 204, 205, 304 responses.
690+
if (Method != "HEAD" && StatusCanHaveBody(StatusCode))
691+
{
692+
// Since the app has completed and we are only now generating
693+
// the headers we can safely set the Content-Length to 0.
694+
OutputAsciiBlock(_bytesContentLengthZero, ref memoryBlock, Memory2, SocketOutput);
695+
}
714696
}
715697
else
716698
{
717-
_keepAlive = false;
699+
if (_httpVersion == HttpVersionType.Http1_1)
700+
{
701+
_autoChunk = true;
702+
OutputAsciiBlock(_bytesTransferEncodingChunked, ref memoryBlock, Memory2, SocketOutput);
703+
}
704+
else
705+
{
706+
_keepAlive = false;
707+
}
718708
}
719709
}
720-
}
721710

722-
if (_keepAlive == false && _responseHeaders.HasConnection == false && _httpVersion == HttpVersionType.Http1_1)
711+
if (_keepAlive == false && _responseHeaders.HasConnection == false && _httpVersion == HttpVersionType.Http1_1)
712+
{
713+
OutputAsciiBlock(_bytesConnectionClose, ref memoryBlock, Memory2, SocketOutput);
714+
}
715+
else if (_keepAlive && _responseHeaders.HasConnection == false && _httpVersion == HttpVersionType.Http1_0)
716+
{
717+
OutputAsciiBlock(_bytesConnectionKeepAlive, ref memoryBlock, Memory2, SocketOutput);
718+
}
719+
else
720+
{
721+
OutputAsciiBlock(_bytesEndLine, ref memoryBlock, Memory2, SocketOutput);
722+
}
723+
}
724+
catch
723725
{
724-
OutputAsciiBlock(_bytesConnectionClose, memoryBlock, SocketOutput);
726+
Memory2.Return(memoryBlock);
727+
throw;
725728
}
726-
else if (_keepAlive && _responseHeaders.HasConnection == false && _httpVersion == HttpVersionType.Http1_0)
729+
var socketOutput = SocketOutput as SocketOutput;
730+
731+
if (socketOutput != null)
727732
{
728-
OutputAsciiBlock(_bytesConnectionKeepAlive, memoryBlock, SocketOutput);
733+
return socketOutput.WriteAsync(memoryBlock, immediate: immediate);
729734
}
730735
else
731736
{
732-
OutputAsciiBlock(_bytesEndLine, memoryBlock, SocketOutput);
737+
try
738+
{
739+
return SocketOutput.WriteAsync(
740+
(memoryBlock.Start == memoryBlock.End) ?
741+
default(ArraySegment<byte>) :
742+
new ArraySegment<byte>(memoryBlock.Array, memoryBlock.Start, memoryBlock.End - memoryBlock.Start),
743+
immediate);
744+
}
745+
finally
746+
{
747+
Memory2.Return(memoryBlock);
748+
}
733749
}
734-
735-
return SocketOutput.WriteAsync(
736-
(memoryBlock.Start == memoryBlock.End) ?
737-
default(ArraySegment<byte>) :
738-
new ArraySegment<byte>(memoryBlock.Array, memoryBlock.Start, memoryBlock.End - memoryBlock.Start),
739-
immediate);
740750
}
741751

742752
private bool TakeStartLine(SocketInput input)

0 commit comments

Comments
 (0)