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

Precomputed header bytes #367

Merged
merged 5 commits into from
Nov 23, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public FilteredStreamAdapter(
IKestrelTrace logger)
{
SocketInput = new SocketInput(memory);
SocketOutput = new StreamSocketOutput(filteredStream);
SocketOutput = new StreamSocketOutput(filteredStream, memory);

_log = logger;
_filteredStream = filteredStream;
Expand Down
20 changes: 18 additions & 2 deletions src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,29 @@ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, Cancel

public override void Write(byte[] buffer, int offset, int count)
{
var segment = new ArraySegment<byte>(buffer, offset, count);
ArraySegment<byte> segment;
if (buffer != null)
{
segment = new ArraySegment<byte>(buffer, offset, count);
}
else
{
segment = default(ArraySegment<byte>);
}
_output.Write(segment);
}

public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
{
var segment = new ArraySegment<byte>(buffer, offset, count);
ArraySegment<byte> segment;
if (buffer != null)
{
segment = new ArraySegment<byte>(buffer, offset, count);
}
else
{
segment = default(ArraySegment<byte>);
}
return _output.WriteAsync(segment, cancellationToken: token);
}

Expand Down
27 changes: 26 additions & 1 deletion src/Microsoft.AspNet.Server.Kestrel/Filter/StreamSocketOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter
public class StreamSocketOutput : ISocketOutput
{
private readonly Stream _outputStream;
private readonly MemoryPool2 _memory;
private MemoryPoolBlock2 _producingBlock;

public StreamSocketOutput(Stream outputStream)
public StreamSocketOutput(Stream outputStream, MemoryPool2 memory)
{
_outputStream = outputStream;
_memory = memory;
}

void ISocketOutput.Write(ArraySegment<byte> buffer, bool immediate)
Expand All @@ -30,5 +33,27 @@ Task ISocketOutput.WriteAsync(ArraySegment<byte> buffer, bool immediate, Cancell
_outputStream.Write(buffer.Array, buffer.Offset, buffer.Count);
return TaskUtilities.CompletedTask;
}

public MemoryPoolIterator2 ProducingStart()
{
_producingBlock = _memory.Lease();
return new MemoryPoolIterator2(_producingBlock);
}

public void ProducingComplete(MemoryPoolIterator2 end, int count)
{
var block = _producingBlock;
while (block != end.Block)
{
_outputStream.Write(block.Data.Array, block.Data.Offset, block.Data.Count);

var returnBlock = block;
block = block.Next;
returnBlock.Pool?.Return(returnBlock);
}

_outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index - end.Block.Data.Offset);
end.Block.Pool?.Return(end.Block);
}
}
}
4 changes: 2 additions & 2 deletions src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public Connection(ListenerContext context, UvStreamHandle socket) : base(context
_connectionId = Interlocked.Increment(ref _lastConnectionId);

_rawSocketInput = new SocketInput(Memory2);
_rawSocketOutput = new SocketOutput(Thread, _socket, this, _connectionId, Log);
_rawSocketOutput = new SocketOutput(Thread, _socket, Memory2, this, _connectionId, Log);
}

public void Start()
Expand Down Expand Up @@ -116,7 +116,7 @@ public void Abort()
// called from a libuv thread.
ThreadPool.QueueUserWorkItem(state =>
{
var connection = (Connection)this;
var connection = (Connection)state;
connection._frame.Abort();
}, this);
}
Expand Down
14 changes: 14 additions & 0 deletions src/Microsoft.AspNet.Server.Kestrel/Http/DateHeaderValueManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Text;
using System.Threading;
using Microsoft.AspNet.Server.Kestrel.Infrastructure;

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

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

public byte[] GetDateHeaderValueBytes()
{
PumpTimer();
return _activeDateBytes ? _dateBytes0 : _dateBytes1;
}

/// <summary>
/// Releases all resources used by the current instance of <see cref="DateHeaderValueManager"/>.
/// </summary>
Expand Down Expand Up @@ -92,6 +102,8 @@ private void PumpTimer()
// here as the timer won't fire until the timer interval has passed and we want a value assigned
// inline now to serve requests that occur in the meantime.
_dateValue = _systemClock.UtcNow.ToString(Constants.RFC1123DateFormat);
Encoding.ASCII.GetBytes(_dateValue, 0, _dateValue.Length, !_activeDateBytes ? _dateBytes0 : _dateBytes1, "\r\nDate: ".Length);
_activeDateBytes = !_activeDateBytes;
_dateValueTimer = new Timer(UpdateDateValue, state: null, dueTime: _timerInterval, period: _timerInterval);
}
}
Expand All @@ -105,6 +117,8 @@ private void UpdateDateValue(object state)

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

if (_hadRequestsSinceLastTimerTick)
{
Expand Down
Loading