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

Commit 07c0b41

Browse files
committed
Merge branch 'benaadams/faster-headers' into dev
2 parents e4fd91b + 81dba39 commit 07c0b41

27 files changed

+1694
-888
lines changed

src/Microsoft.AspNet.Server.Kestrel/Filter/FilteredStreamAdapter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public FilteredStreamAdapter(
2222
IKestrelTrace logger)
2323
{
2424
SocketInput = new SocketInput(memory);
25-
SocketOutput = new StreamSocketOutput(filteredStream);
25+
SocketOutput = new StreamSocketOutput(filteredStream, memory);
2626

2727
_log = logger;
2828
_filteredStream = filteredStream;

src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,29 @@ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, Cancel
6868

6969
public override void Write(byte[] buffer, int offset, int count)
7070
{
71-
var segment = new ArraySegment<byte>(buffer, offset, count);
71+
ArraySegment<byte> segment;
72+
if (buffer != null)
73+
{
74+
segment = new ArraySegment<byte>(buffer, offset, count);
75+
}
76+
else
77+
{
78+
segment = default(ArraySegment<byte>);
79+
}
7280
_output.Write(segment);
7381
}
7482

7583
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
7684
{
77-
var segment = new ArraySegment<byte>(buffer, offset, count);
85+
ArraySegment<byte> segment;
86+
if (buffer != null)
87+
{
88+
segment = new ArraySegment<byte>(buffer, offset, count);
89+
}
90+
else
91+
{
92+
segment = default(ArraySegment<byte>);
93+
}
7894
return _output.WriteAsync(segment, cancellationToken: token);
7995
}
8096

src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter
1313
public class StreamSocketOutput : ISocketOutput
1414
{
1515
private readonly Stream _outputStream;
16+
private readonly MemoryPool2 _memory;
17+
private MemoryPoolBlock2 _producingBlock;
1618

17-
public StreamSocketOutput(Stream outputStream)
19+
public StreamSocketOutput(Stream outputStream, MemoryPool2 memory)
1820
{
1921
_outputStream = outputStream;
22+
_memory = memory;
2023
}
2124

2225
void ISocketOutput.Write(ArraySegment<byte> buffer, bool immediate)
@@ -30,5 +33,27 @@ Task ISocketOutput.WriteAsync(ArraySegment<byte> buffer, bool immediate, Cancell
3033
_outputStream.Write(buffer.Array, buffer.Offset, buffer.Count);
3134
return TaskUtilities.CompletedTask;
3235
}
36+
37+
public MemoryPoolIterator2 ProducingStart()
38+
{
39+
_producingBlock = _memory.Lease();
40+
return new MemoryPoolIterator2(_producingBlock);
41+
}
42+
43+
public void ProducingComplete(MemoryPoolIterator2 end, int count)
44+
{
45+
var block = _producingBlock;
46+
while (block != end.Block)
47+
{
48+
_outputStream.Write(block.Data.Array, block.Data.Offset, block.Data.Count);
49+
50+
var returnBlock = block;
51+
block = block.Next;
52+
returnBlock.Pool?.Return(returnBlock);
53+
}
54+
55+
_outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index - end.Block.Data.Offset);
56+
end.Block.Pool?.Return(end.Block);
57+
}
3358
}
3459
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public Connection(ListenerContext context, UvStreamHandle socket) : base(context
4242
_connectionId = Interlocked.Increment(ref _lastConnectionId);
4343

4444
_rawSocketInput = new SocketInput(Memory2);
45-
_rawSocketOutput = new SocketOutput(Thread, _socket, this, _connectionId, Log);
45+
_rawSocketOutput = new SocketOutput(Thread, _socket, Memory2, this, _connectionId, Log);
4646
}
4747

4848
public void Start()
@@ -116,7 +116,7 @@ public void Abort()
116116
// called from a libuv thread.
117117
ThreadPool.QueueUserWorkItem(state =>
118118
{
119-
var connection = (Connection)this;
119+
var connection = (Connection)state;
120120
connection._frame.Abort();
121121
}, this);
122122
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Text;
56
using System.Threading;
67
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
78

@@ -17,6 +18,9 @@ public class DateHeaderValueManager : IDisposable
1718
private readonly TimeSpan _timerInterval;
1819

1920
private volatile string _dateValue;
21+
private volatile bool _activeDateBytes;
22+
private readonly byte[] _dateBytes0 = Encoding.ASCII.GetBytes("\r\nDate: DDD, dd mmm yyyy hh:mm:ss GMT");
23+
private readonly byte[] _dateBytes1 = Encoding.ASCII.GetBytes("\r\nDate: DDD, dd mmm yyyy hh:mm:ss GMT");
2024
private object _timerLocker = new object();
2125
private bool _isDisposed = false;
2226
private bool _hadRequestsSinceLastTimerTick = false;
@@ -62,6 +66,12 @@ public virtual string GetDateHeaderValue()
6266
return _dateValue ?? _systemClock.UtcNow.ToString(Constants.RFC1123DateFormat);
6367
}
6468

69+
public byte[] GetDateHeaderValueBytes()
70+
{
71+
PumpTimer();
72+
return _activeDateBytes ? _dateBytes0 : _dateBytes1;
73+
}
74+
6575
/// <summary>
6676
/// Releases all resources used by the current instance of <see cref="DateHeaderValueManager"/>.
6777
/// </summary>
@@ -92,6 +102,8 @@ private void PumpTimer()
92102
// here as the timer won't fire until the timer interval has passed and we want a value assigned
93103
// inline now to serve requests that occur in the meantime.
94104
_dateValue = _systemClock.UtcNow.ToString(Constants.RFC1123DateFormat);
105+
Encoding.ASCII.GetBytes(_dateValue, 0, _dateValue.Length, !_activeDateBytes ? _dateBytes0 : _dateBytes1, "\r\nDate: ".Length);
106+
_activeDateBytes = !_activeDateBytes;
95107
_dateValueTimer = new Timer(UpdateDateValue, state: null, dueTime: _timerInterval, period: _timerInterval);
96108
}
97109
}
@@ -105,6 +117,8 @@ private void UpdateDateValue(object state)
105117

106118
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18 for required format of Date header
107119
_dateValue = now.ToString(Constants.RFC1123DateFormat);
120+
Encoding.ASCII.GetBytes(_dateValue, 0, _dateValue.Length, !_activeDateBytes ? _dateBytes0 : _dateBytes1, "\r\nDate: ".Length);
121+
_activeDateBytes = !_activeDateBytes;
108122

109123
if (_hadRequestsSinceLastTimerTick)
110124
{

0 commit comments

Comments
 (0)