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

Commit 6c7684a

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

File tree

4 files changed

+174
-17
lines changed

4 files changed

+174
-17
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 & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
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
89
{
910

1011
public partial class FrameRequestHeaders
1112
{
12-
1313
private long _bits = 0;
1414

1515
private StringValues _CacheControl;
@@ -592,7 +592,8 @@ public StringValues HeaderUserAgent
592592

593593
protected override int GetCountFast()
594594
{
595-
return BitCount(_bits) + (MaybeUnknown?.Count ?? 0);
595+
return BitCount(_bits)
596+
+ (MaybeUnknown?.Count ?? 0);
596597
}
597598

598599
protected override StringValues GetValueFast(string key)
@@ -5038,7 +5039,6 @@ public partial class FrameResponseHeaders
50385039
private static byte[] _bytesSetCookie = Encoding.ASCII.GetBytes("Set-Cookie: ");
50395040
private static byte[] _bytesVary = Encoding.ASCII.GetBytes("Vary: ");
50405041
private static byte[] _bytesWWWAuthenticate = Encoding.ASCII.GetBytes("WWW-Authenticate: ");
5041-
50425042
private long _bits = 0;
50435043

50445044
private StringValues _CacheControl;
@@ -5071,6 +5071,26 @@ public partial class FrameResponseHeaders
50715071
private StringValues _SetCookie;
50725072
private StringValues _Vary;
50735073
private StringValues _WWWAuthenticate;
5074+
private bool _hasDefaultServer;
5075+
private bool _hasDefaultDate;
5076+
5077+
public bool HasDefaultServer {
5078+
get { return _hasDefaultServer; }
5079+
set
5080+
{
5081+
_hasDefaultServer = value;
5082+
_bits &= ~67108864L;
5083+
}
5084+
}
5085+
5086+
public bool HasDefaultDate {
5087+
get { return _hasDefaultDate; }
5088+
set
5089+
{
5090+
_hasDefaultDate = value;
5091+
_bits &= ~4L;
5092+
}
5093+
}
50745094

50755095
public StringValues HeaderCacheControl
50765096
{
@@ -5108,6 +5128,7 @@ public StringValues HeaderDate
51085128
set
51095129
{
51105130
_bits |= 4L;
5131+
HasDefaultDate = false;
51115132
_Date = value;
51125133
}
51135134
}
@@ -5422,6 +5443,7 @@ public StringValues HeaderServer
54225443
set
54235444
{
54245445
_bits |= 67108864L;
5446+
HasDefaultServer = false;
54255447
_Server = value;
54265448
}
54275449
}
@@ -5467,7 +5489,9 @@ public StringValues HeaderWWWAuthenticate
54675489

54685490
protected override int GetCountFast()
54695491
{
5470-
return BitCount(_bits) + (MaybeUnknown?.Count ?? 0);
5492+
return BitCount(_bits) + (HasDefaultDate ? 1 : 0)
5493+
+ (HasDefaultServer ? 1 : 0)
5494+
+ (MaybeUnknown?.Count ?? 0);
54715495
}
54725496

54735497
protected override StringValues GetValueFast(string key)
@@ -6007,6 +6031,11 @@ protected override bool TryGetValueFast(string key, out StringValues value)
60076031
{
60086032
if ("Date".Equals(key, StringComparison.OrdinalIgnoreCase))
60096033
{
6034+
if (HasDefaultDate)
6035+
{
6036+
value = DateTime.UtcNow.ToString(Constants.RFC1123DateFormat);
6037+
return true;
6038+
}
60106039
if (((_bits & 4L) != 0))
60116040
{
60126041
value = _Date;
@@ -6067,6 +6096,11 @@ protected override bool TryGetValueFast(string key, out StringValues value)
60676096

60686097
if ("Server".Equals(key, StringComparison.OrdinalIgnoreCase))
60696098
{
6099+
if (HasDefaultServer)
6100+
{
6101+
value = "Kestrel";
6102+
return true;
6103+
}
60706104
if (((_bits & 67108864L) != 0))
60716105
{
60726106
value = _Server;
@@ -6441,6 +6475,7 @@ protected override void SetValueFast(string key, StringValues value)
64416475
{
64426476
_bits |= 4L;
64436477
_Date = value;
6478+
HasDefaultDate = false;
64446479
return;
64456480
}
64466481

@@ -6473,6 +6508,7 @@ protected override void SetValueFast(string key, StringValues value)
64736508
{
64746509
_bits |= 67108864L;
64756510
_Server = value;
6511+
HasDefaultServer = false;
64766512
return;
64776513
}
64786514
}
@@ -6745,6 +6781,7 @@ protected override void AddValueFast(string key, StringValues value)
67456781
}
67466782
_bits |= 4L;
67476783
_Date = value;
6784+
HasDefaultDate = false;
67486785
return;
67496786
}
67506787

@@ -6793,6 +6830,7 @@ protected override void AddValueFast(string key, StringValues value)
67936830
}
67946831
_bits |= 67108864L;
67956832
_Server = value;
6833+
HasDefaultServer = false;
67966834
return;
67976835
}
67986836
}
@@ -7156,6 +7194,7 @@ protected override bool RemoveFast(string key)
71567194
{
71577195
_bits &= ~4L;
71587196
_Date = StringValues.Empty;
7197+
HasDefaultDate = false;
71597198
return true;
71607199
}
71617200
else
@@ -7216,6 +7255,7 @@ protected override bool RemoveFast(string key)
72167255
{
72177256
_bits &= ~67108864L;
72187257
_Server = StringValues.Empty;
7258+
HasDefaultServer = false;
72197259
return true;
72207260
}
72217261
else
@@ -7557,6 +7597,8 @@ protected override void ClearFast()
75577597
HasConnection = false;
75587598
HasTransferEncoding = false;
75597599
HasContentLength = false;
7600+
HasDefaultServer = false;
7601+
HasDefaultDate = false;
75607602
}
75617603

75627604
protected override void CopyToFast(KeyValuePair<string, StringValues>[] array, int arrayIndex)
@@ -8023,6 +8065,7 @@ public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string
80238065
else
80248066
{
80258067
_bits |= 4L;
8068+
HasDefaultDate = false;
80268069
_Date = new StringValues(value);
80278070
}
80288071
return;
@@ -8083,6 +8126,7 @@ public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string
80838126
else
80848127
{
80858128
_bits |= 67108864L;
8129+
HasDefaultServer = false;
80868130
_Server = new StringValues(value);
80878131
}
80888132
return;
@@ -8504,6 +8548,12 @@ public bool MoveNext()
85048548
}
85058549

85068550
state2:
8551+
if (_collection.HasDefaultDate)
8552+
{
8553+
_current = new KeyValuePair<string, StringValues>("Date", DateTime.UtcNow.ToString(Constants.RFC1123DateFormat));
8554+
_state = 3;
8555+
return true;
8556+
}
85078557
if (((_bits & 4L) != 0))
85088558
{
85098559
_current = new KeyValuePair<string, StringValues>("Date", _collection._Date);
@@ -8696,6 +8746,12 @@ public bool MoveNext()
86968746
}
86978747

86988748
state26:
8749+
if (_collection.HasDefaultServer)
8750+
{
8751+
_current = new KeyValuePair<string, StringValues>("Server", "Kestrel");
8752+
_state = 27;
8753+
return true;
8754+
}
86998755
if (((_bits & 67108864L) != 0))
87008756
{
87018757
_current = new KeyValuePair<string, StringValues>("Server", _collection._Server);

0 commit comments

Comments
 (0)