Skip to content

Commit e75165f

Browse files
committed
Remove min buffer size
1 parent 5f8258c commit e75165f

File tree

3 files changed

+180
-102
lines changed

3 files changed

+180
-102
lines changed

src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ public class Http1OutputProducer : IHttpOutputProducer, IHttpOutputAborter, IDis
4343
private long _unflushedBytes;
4444
private bool _autoChunk;
4545
private readonly PipeWriter _pipeWriter;
46-
private const int MemorySizeThreshold = 1024;
4746
private const int BeginChunkLengthMax = 5;
4847
private const int EndChunkLength = 2;
4948

@@ -606,7 +605,7 @@ private void EnsureCapacity(int sizeHint)
606605

607606
// If the sizeHint is 0, any capacity will do
608607
// Otherwise, the buffer must have enough space for the entire size hint, or we need to add a segment.
609-
if ((sizeHint == 0 && remainingSize > 0) || (sizeHint > 0 && remainingSize >= Math.Min(MemorySizeThreshold, sizeHint)))
608+
if ((sizeHint == 0 && remainingSize > 0) || (sizeHint > 0 && remainingSize >= sizeHint))
610609
{
611610
// We have capacity in the current segment
612611
return;

src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedResponseTests.cs

Lines changed: 158 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -421,21 +421,61 @@ await connection.Receive(
421421
}
422422
}
423423

424-
[Theory]
425-
[InlineData(false)]
426-
[InlineData(true)]
427-
public async Task ChunksWithGetMemoryBeforeFirstFlushStillFlushes(bool start)
424+
[Fact]
425+
public async Task ChunksWithGetMemoryAfterStartAsyncBeforeFirstFlushStillFlushes()
428426
{
429427
var testContext = new TestServiceContext(LoggerFactory);
430428

431429
using (var server = new TestServer(async httpContext =>
432430
{
433431
var response = httpContext.Response;
434432

435-
if (start)
433+
await response.StartAsync();
434+
var memory = response.BodyPipe.GetMemory();
435+
var fisrtPartOfResponse = Encoding.ASCII.GetBytes("Hello ");
436+
fisrtPartOfResponse.CopyTo(memory);
437+
response.BodyPipe.Advance(6);
438+
439+
memory = response.BodyPipe.GetMemory();
440+
var secondPartOfResponse = Encoding.ASCII.GetBytes("World!");
441+
secondPartOfResponse.CopyTo(memory);
442+
response.BodyPipe.Advance(6);
443+
444+
await response.BodyPipe.FlushAsync();
445+
}, testContext))
446+
{
447+
using (var connection = server.CreateConnection())
436448
{
437-
await response.StartAsync();
449+
await connection.Send(
450+
"GET / HTTP/1.1",
451+
"Host: ",
452+
"",
453+
"");
454+
await connection.Receive(
455+
"HTTP/1.1 200 OK",
456+
$"Date: {testContext.DateHeaderValue}",
457+
"Transfer-Encoding: chunked",
458+
"",
459+
"c",
460+
"Hello World!",
461+
"0",
462+
"",
463+
"");
438464
}
465+
466+
await server.StopAsync();
467+
}
468+
}
469+
470+
[Fact]
471+
public async Task ChunksWithGetMemoryBeforeFirstFlushStillFlushes()
472+
{
473+
var testContext = new TestServiceContext(LoggerFactory);
474+
475+
using (var server = new TestServer(async httpContext =>
476+
{
477+
var response = httpContext.Response;
478+
439479
var memory = response.BodyPipe.GetMemory();
440480
var fisrtPartOfResponse = Encoding.ASCII.GetBytes("Hello ");
441481
fisrtPartOfResponse.CopyTo(memory);
@@ -472,10 +512,8 @@ await connection.Receive(
472512
}
473513
}
474514

475-
[Theory]
476-
[InlineData(false)]
477-
[InlineData(true)]
478-
public async Task ChunksWithGetMemoryLargeWriteBeforeFirstFlush(bool start)
515+
[Fact]
516+
public async Task ChunksWithGetMemoryLargeWriteBeforeFirstFlush()
479517
{
480518
var length = new IntAsRef();
481519
var semaphore = new SemaphoreSlim(initialCount: 0);
@@ -484,10 +522,6 @@ public async Task ChunksWithGetMemoryLargeWriteBeforeFirstFlush(bool start)
484522
using (var server = new TestServer(async httpContext =>
485523
{
486524
var response = httpContext.Response;
487-
if (start)
488-
{
489-
await response.StartAsync();
490-
}
491525

492526
var memory = response.BodyPipe.GetMemory();
493527
length.Value = memory.Length;
@@ -534,10 +568,8 @@ await connection.Receive(
534568
}
535569
}
536570

537-
[Theory]
538-
[InlineData(false)]
539-
[InlineData(true)]
540-
public async Task ChunksWithGetMemoryWithInitialFlushWorks(bool start)
571+
[Fact]
572+
public async Task ChunksWithGetMemoryAndStartAsyncWithInitialFlushWorks()
541573
{
542574
var length = new IntAsRef();
543575
var semaphore = new SemaphoreSlim(initialCount: 0);
@@ -547,10 +579,7 @@ public async Task ChunksWithGetMemoryWithInitialFlushWorks(bool start)
547579
{
548580
var response = httpContext.Response;
549581

550-
if (start)
551-
{
552-
await response.StartAsync();
553-
}
582+
await response.StartAsync();
554583

555584
await response.BodyPipe.FlushAsync();
556585

@@ -599,22 +628,76 @@ await connection.Receive(
599628
}
600629
}
601630

602-
[Theory]
603-
[InlineData(false)]
604-
[InlineData(true)]
605-
public async Task ChunkGetMemoryMultipleAdvance(bool start)
631+
[Fact]
632+
public async Task ChunksWithGetMemoryBeforeFlushEdgeCase()
606633
{
634+
var length = new IntAsRef();
635+
var semaphore = new SemaphoreSlim(initialCount: 0);
607636
var testContext = new TestServiceContext(LoggerFactory);
608637

609638
using (var server = new TestServer(async httpContext =>
610639
{
611640
var response = httpContext.Response;
612641

613-
if (start)
642+
await response.StartAsync();
643+
644+
var memory = response.BodyPipe.GetMemory();
645+
length.Value = memory.Length - 1;
646+
semaphore.Release();
647+
648+
var fisrtPartOfResponse = Encoding.ASCII.GetBytes(new string('a', length.Value));
649+
fisrtPartOfResponse.CopyTo(memory);
650+
response.BodyPipe.Advance(length.Value);
651+
652+
var secondMemory = response.BodyPipe.GetMemory(6);
653+
654+
var secondPartOfResponse = Encoding.ASCII.GetBytes("World!");
655+
secondPartOfResponse.CopyTo(secondMemory);
656+
response.BodyPipe.Advance(6);
657+
658+
await response.BodyPipe.FlushAsync();
659+
}, testContext))
660+
{
661+
using (var connection = server.CreateConnection())
614662
{
615-
await response.StartAsync();
663+
await connection.Send(
664+
"GET / HTTP/1.1",
665+
"Host: ",
666+
"",
667+
"");
668+
669+
// Wait for length to be set
670+
await semaphore.WaitAsync();
671+
672+
await connection.Receive(
673+
"HTTP/1.1 200 OK",
674+
$"Date: {testContext.DateHeaderValue}",
675+
"Transfer-Encoding: chunked",
676+
"",
677+
length.Value.ToString("x"),
678+
new string('a', length.Value),
679+
"6",
680+
"World!",
681+
"0",
682+
"",
683+
"");
616684
}
617685

686+
await server.StopAsync();
687+
}
688+
}
689+
690+
[Fact]
691+
public async Task ChunkGetMemoryMultipleAdvance()
692+
{
693+
var testContext = new TestServiceContext(LoggerFactory);
694+
695+
using (var server = new TestServer(async httpContext =>
696+
{
697+
var response = httpContext.Response;
698+
699+
await response.StartAsync();
700+
618701
var memory = response.BodyPipe.GetMemory(4096);
619702
var fisrtPartOfResponse = Encoding.ASCII.GetBytes("Hello ");
620703
fisrtPartOfResponse.CopyTo(memory);
@@ -648,20 +731,16 @@ await connection.Receive(
648731
}
649732
}
650733

651-
[Theory]
652-
[InlineData(false)]
653-
[InlineData(true)]
654-
public async Task ChunkGetSpanMultipleAdvance(bool start)
734+
[Fact]
735+
public async Task ChunkGetSpanMultipleAdvance()
655736
{
656737
var testContext = new TestServiceContext(LoggerFactory);
657738

658739
using (var server = new TestServer(async httpContext =>
659740
{
660741
var response = httpContext.Response;
661-
if (start)
662-
{
663-
await response.StartAsync();
664-
}
742+
await response.StartAsync();
743+
665744
// To avoid using span in an async method
666745
void NonAsyncMethod()
667746
{
@@ -863,27 +942,21 @@ await connection.Receive(
863942
}
864943

865944
[Theory]
866-
[InlineData(15, false)]
867-
[InlineData(255, false)]
868-
[InlineData(15, true)]
869-
[InlineData(255, true)]
870-
public async Task ChunkGetMemoryWithSmallerSizesWork(int writeSize, bool start)
945+
[InlineData(15)]
946+
[InlineData(255)]
947+
public async Task ChunkGetMemoryWithoutStartWithSmallerSizesWork(int writeSize)
871948
{
872949
var testContext = new TestServiceContext(LoggerFactory);
873950

874951
using (var server = new TestServer(async httpContext =>
875952
{
876953
var response = httpContext.Response;
877954

878-
if (start)
879-
{
880-
await response.StartAsync();
881-
}
882-
883955
var memory = response.BodyPipe.GetMemory(4096);
884956
var fisrtPartOfResponse = Encoding.ASCII.GetBytes(new string('a', writeSize));
885957
fisrtPartOfResponse.CopyTo(memory);
886958
response.BodyPipe.Advance(writeSize);
959+
await response.BodyPipe.FlushAsync();
887960
}, testContext))
888961
{
889962
using (var connection = server.CreateConnection())
@@ -910,19 +983,53 @@ await connection.Receive(
910983
}
911984

912985
[Theory]
913-
[InlineData(false)]
914-
[InlineData(true)]
915-
public async Task ChunkedWithBothPipeAndStreamWorks(bool start)
986+
[InlineData(15)]
987+
[InlineData(255)]
988+
public async Task ChunkGetMemoryWithStartWithSmallerSizesWork(int writeSize)
916989
{
990+
var testContext = new TestServiceContext(LoggerFactory);
991+
917992
using (var server = new TestServer(async httpContext =>
918993
{
919994
var response = httpContext.Response;
920995

921-
if (start)
996+
var memory = response.BodyPipe.GetMemory(4096);
997+
var fisrtPartOfResponse = Encoding.ASCII.GetBytes(new string('a', writeSize));
998+
fisrtPartOfResponse.CopyTo(memory);
999+
response.BodyPipe.Advance(writeSize);
1000+
await response.BodyPipe.FlushAsync();
1001+
}, testContext))
1002+
{
1003+
using (var connection = server.CreateConnection())
9221004
{
923-
await response.StartAsync();
1005+
await connection.Send(
1006+
"GET / HTTP/1.1",
1007+
"Host: ",
1008+
"",
1009+
"");
1010+
await connection.Receive(
1011+
"HTTP/1.1 200 OK",
1012+
$"Date: {testContext.DateHeaderValue}",
1013+
"Transfer-Encoding: chunked",
1014+
"",
1015+
writeSize.ToString("X").ToLower(),
1016+
new string('a', writeSize),
1017+
"0",
1018+
"",
1019+
"");
9241020
}
9251021

1022+
await server.StopAsync();
1023+
}
1024+
}
1025+
1026+
[Fact]
1027+
public async Task ChunkedWithBothPipeAndStreamWorks()
1028+
{
1029+
using (var server = new TestServer(async httpContext =>
1030+
{
1031+
var response = httpContext.Response;
1032+
9261033
var memory = response.BodyPipe.GetMemory(4096);
9271034
var fisrtPartOfResponse = Encoding.ASCII.GetBytes("hello,");
9281035
fisrtPartOfResponse.CopyTo(memory);

0 commit comments

Comments
 (0)