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

Commit d9cf936

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

File tree

4 files changed

+174
-14
lines changed

4 files changed

+174
-14
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: 15 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();
@@ -176,8 +178,8 @@ public void Reset()
176178
public void ResetResponseHeaders()
177179
{
178180
_responseHeaders.Reset();
179-
_responseHeaders.HeaderServer = "Kestrel";
180-
_responseHeaders.HeaderDate = DateHeaderValueManager.GetDateHeaderValue();
181+
_responseHeaders.HasDefaultDate = true;
182+
_responseHeaders.HasDefaultServer = true;
181183
}
182184

183185
/// <summary>
@@ -612,6 +614,13 @@ private Task CreateResponseHeader(
612614

613615
OutputAsciiBlock(statusBytes, memoryBlock, SocketOutput);
614616

617+
if (_responseHeaders.HasDefaultDate)
618+
{
619+
OutputAsciiBlock(_bytesDate, memoryBlock, SocketOutput);
620+
OutputAsciiBlock(DateHeaderValueManager.GetDateHeaderValueBytes(), memoryBlock, SocketOutput);
621+
OutputAsciiBlock(_bytesEndLine, memoryBlock, SocketOutput);
622+
}
623+
615624
foreach (var header in _responseHeaders.AsOutputEnumerable())
616625
{
617626
foreach (var value in header.Value)
@@ -625,7 +634,11 @@ private Task CreateResponseHeader(
625634
_keepAlive = false;
626635
}
627636
}
637+
}
628638

639+
if (_responseHeaders.HasDefaultServer)
640+
{
641+
OutputAsciiBlock(_bytesServer, memoryBlock, SocketOutput);
629642
}
630643

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

src/Microsoft.AspNet.Server.Kestrel/Http/FrameHeaders.Generated.cs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections.Generic;
44
using System.Text;
5+
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
56
using Microsoft.Extensions.Primitives;
67

78
namespace Microsoft.AspNet.Server.Kestrel.Http
@@ -592,7 +593,8 @@ public StringValues HeaderUserAgent
592593

593594
protected override int GetCountFast()
594595
{
595-
return BitCount(_bits) + (MaybeUnknown?.Count ?? 0);
596+
return BitCount(_bits)
597+
+ (MaybeUnknown?.Count ?? 0);
596598
}
597599

598600
protected override StringValues GetValueFast(string key)
@@ -5071,6 +5073,26 @@ public partial class FrameResponseHeaders
50715073
private StringValues _SetCookie;
50725074
private StringValues _Vary;
50735075
private StringValues _WWWAuthenticate;
5076+
private bool _hasDefaultServer;
5077+
private bool _hasDefaultDate;
5078+
5079+
public bool HasDefaultServer {
5080+
get { return _hasDefaultServer; }
5081+
set
5082+
{
5083+
_hasDefaultServer = value;
5084+
_bits &= ~67108864L;
5085+
}
5086+
}
5087+
5088+
public bool HasDefaultDate {
5089+
get { return _hasDefaultDate; }
5090+
set
5091+
{
5092+
_hasDefaultDate = value;
5093+
_bits &= ~4L;
5094+
}
5095+
}
50745096

50755097
public StringValues HeaderCacheControl
50765098
{
@@ -5108,6 +5130,7 @@ public StringValues HeaderDate
51085130
set
51095131
{
51105132
_bits |= 4L;
5133+
HasDefaultDate = false;
51115134
_Date = value;
51125135
}
51135136
}
@@ -5422,6 +5445,7 @@ public StringValues HeaderServer
54225445
set
54235446
{
54245447
_bits |= 67108864L;
5448+
HasDefaultServer = false;
54255449
_Server = value;
54265450
}
54275451
}
@@ -5467,7 +5491,9 @@ public StringValues HeaderWWWAuthenticate
54675491

54685492
protected override int GetCountFast()
54695493
{
5470-
return BitCount(_bits) + (MaybeUnknown?.Count ?? 0);
5494+
return BitCount(_bits) + (HasDefaultDate ? 1 : 0)
5495+
+ (HasDefaultServer ? 1 : 0)
5496+
+ (MaybeUnknown?.Count ?? 0);
54715497
}
54725498

54735499
protected override StringValues GetValueFast(string key)
@@ -6007,6 +6033,11 @@ protected override bool TryGetValueFast(string key, out StringValues value)
60076033
{
60086034
if ("Date".Equals(key, StringComparison.OrdinalIgnoreCase))
60096035
{
6036+
if (HasDefaultDate)
6037+
{
6038+
value = DateTime.UtcNow.ToString(Constants.RFC1123DateFormat);
6039+
return true;
6040+
}
60106041
if (((_bits & 4L) != 0))
60116042
{
60126043
value = _Date;
@@ -6067,6 +6098,11 @@ protected override bool TryGetValueFast(string key, out StringValues value)
60676098

60686099
if ("Server".Equals(key, StringComparison.OrdinalIgnoreCase))
60696100
{
6101+
if (HasDefaultServer)
6102+
{
6103+
value = "Kestrel";
6104+
return true;
6105+
}
60706106
if (((_bits & 67108864L) != 0))
60716107
{
60726108
value = _Server;
@@ -6441,6 +6477,7 @@ protected override void SetValueFast(string key, StringValues value)
64416477
{
64426478
_bits |= 4L;
64436479
_Date = value;
6480+
HasDefaultDate = false;
64446481
return;
64456482
}
64466483

@@ -6473,6 +6510,7 @@ protected override void SetValueFast(string key, StringValues value)
64736510
{
64746511
_bits |= 67108864L;
64756512
_Server = value;
6513+
HasDefaultServer = false;
64766514
return;
64776515
}
64786516
}
@@ -6745,6 +6783,7 @@ protected override void AddValueFast(string key, StringValues value)
67456783
}
67466784
_bits |= 4L;
67476785
_Date = value;
6786+
HasDefaultDate = false;
67486787
return;
67496788
}
67506789

@@ -6793,6 +6832,7 @@ protected override void AddValueFast(string key, StringValues value)
67936832
}
67946833
_bits |= 67108864L;
67956834
_Server = value;
6835+
HasDefaultServer = false;
67966836
return;
67976837
}
67986838
}
@@ -7156,6 +7196,7 @@ protected override bool RemoveFast(string key)
71567196
{
71577197
_bits &= ~4L;
71587198
_Date = StringValues.Empty;
7199+
HasDefaultDate = false;
71597200
return true;
71607201
}
71617202
else
@@ -7216,6 +7257,7 @@ protected override bool RemoveFast(string key)
72167257
{
72177258
_bits &= ~67108864L;
72187259
_Server = StringValues.Empty;
7260+
HasDefaultServer = false;
72197261
return true;
72207262
}
72217263
else
@@ -7557,6 +7599,8 @@ protected override void ClearFast()
75577599
HasConnection = false;
75587600
HasTransferEncoding = false;
75597601
HasContentLength = false;
7602+
HasDefaultServer = false;
7603+
HasDefaultDate = false;
75607604
}
75617605

75627606
protected override void CopyToFast(KeyValuePair<string, StringValues>[] array, int arrayIndex)
@@ -8023,6 +8067,7 @@ public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string
80238067
else
80248068
{
80258069
_bits |= 4L;
8070+
HasDefaultDate = false;
80268071
_Date = new StringValues(value);
80278072
}
80288073
return;
@@ -8083,6 +8128,7 @@ public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string
80838128
else
80848129
{
80858130
_bits |= 67108864L;
8131+
HasDefaultServer = false;
80868132
_Server = new StringValues(value);
80878133
}
80888134
return;
@@ -8504,6 +8550,12 @@ public bool MoveNext()
85048550
}
85058551

85068552
state2:
8553+
if (_collection.HasDefaultDate)
8554+
{
8555+
_current = new KeyValuePair<string, StringValues>("Date", DateTime.UtcNow.ToString(Constants.RFC1123DateFormat));
8556+
_state = 3;
8557+
return true;
8558+
}
85078559
if (((_bits & 4L) != 0))
85088560
{
85098561
_current = new KeyValuePair<string, StringValues>("Date", _collection._Date);
@@ -8696,6 +8748,12 @@ public bool MoveNext()
86968748
}
86978749

86988750
state26:
8751+
if (_collection.HasDefaultServer)
8752+
{
8753+
_current = new KeyValuePair<string, StringValues>("Server", "Kestrel");
8754+
_state = 27;
8755+
return true;
8756+
}
86998757
if (((_bits & 67108864L) != 0))
87008758
{
87018759
_current = new KeyValuePair<string, StringValues>("Server", _collection._Server);

0 commit comments

Comments
 (0)