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

Commit 0fa105d

Browse files
committed
Precompute Server and Date bytes
1 parent 0ed64bd commit 0fa105d

File tree

4 files changed

+489
-331
lines changed

4 files changed

+489
-331
lines changed

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 int _activeDateBytes;
22+
private byte[] _dateBytes0 = Encoding.ASCII.GetBytes("DDD, dd mmm yyyy hh:mm:ss GMT");
23+
private byte[] _dateBytes1 = Encoding.ASCII.GetBytes("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 == 0 ? _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 ^ 1) == 0 ? _dateBytes0 : _dateBytes1, 0);
106+
_activeDateBytes ^= 1;
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 ^ 1) == 0 ? _dateBytes0 : _dateBytes1, 0);
121+
_activeDateBytes ^= 1;
108122

109123
if (_hadRequestsSinceLastTimerTick)
110124
{

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public partial class Frame : FrameContext, IFrameControl
3636
private static readonly byte[] _bytesHttpVersion1_1 = Encoding.ASCII.GetBytes("HTTP/1.1 ");
3737
private static readonly byte[] _bytesContentLengthZero = Encoding.ASCII.GetBytes("Content-Length: 0\r\n");
3838
private static readonly byte[] _bytesSpace = Encoding.ASCII.GetBytes(" ");
39+
private static readonly byte[] _bytesServer = Encoding.ASCII.GetBytes("Server: Kestrel\r\n");
40+
private static readonly byte[] _bytesDate = Encoding.ASCII.GetBytes("Date: ");
3941

4042
private readonly object _onStartingSync = new Object();
4143
private readonly object _onCompletedSync = new Object();
@@ -112,6 +114,7 @@ public string HttpVersion
112114
}
113115
}
114116
}
117+
115118
public IHeaderDictionary RequestHeaders { get; set; }
116119
public MessageBody MessageBody { get; set; }
117120
public Stream RequestBody { get; set; }
@@ -176,8 +179,8 @@ public void Reset()
176179
public void ResetResponseHeaders()
177180
{
178181
_responseHeaders.Reset();
179-
_responseHeaders.HeaderServer = "Kestrel";
180-
_responseHeaders.HeaderDate = DateHeaderValueManager.GetDateHeaderValue();
182+
_responseHeaders.HasDefaultDate = true;
183+
_responseHeaders.HasDefaultServer = true;
181184
}
182185

183186
/// <summary>
@@ -612,6 +615,13 @@ private Task CreateResponseHeader(
612615

613616
OutputAsciiBlock(statusBytes, memoryBlock, SocketOutput);
614617

618+
if (_responseHeaders.HasDefaultDate)
619+
{
620+
OutputAsciiBlock(_bytesDate, memoryBlock, SocketOutput);
621+
OutputAsciiBlock(DateHeaderValueManager.GetDateHeaderValueBytes(), memoryBlock, SocketOutput);
622+
OutputAsciiBlock(_bytesEndLine, memoryBlock, SocketOutput);
623+
}
624+
615625
foreach (var header in _responseHeaders.AsOutputEnumerable())
616626
{
617627
foreach (var value in header.Value)
@@ -625,7 +635,11 @@ private Task CreateResponseHeader(
625635
_keepAlive = false;
626636
}
627637
}
638+
}
628639

640+
if (_responseHeaders.HasDefaultServer)
641+
{
642+
OutputAsciiBlock(_bytesServer, memoryBlock, SocketOutput);
629643
}
630644

631645
if (_keepAlive && !_responseHeaders.HasTransferEncoding && !_responseHeaders.HasContentLength)

0 commit comments

Comments
 (0)