Skip to content

Commit

Permalink
Review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
ladeak committed Sep 11, 2024
1 parent 8878dad commit bfc2e12
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.FlowControl;
/// <seealso href="https://datatracker.ietf.org/doc/html/rfc9113#name-flow-control"/>
internal sealed class InputFlowControl
{
private record struct FlowControlState
private struct FlowControlState
{
private const long AbortedBitMask = 1L << 32; // uint MaxValue + 1
internal long _state;
Expand All @@ -35,7 +35,7 @@ public FlowControlState(uint initialWindowSize, bool isAborted)

public uint Available => (uint)_state;

public bool IsAborted => (_state & AbortedBitMask) > 0;
public bool IsAborted => _state > uint.MaxValue;
}

private readonly uint _initialWindowSize;
Expand Down Expand Up @@ -84,7 +84,7 @@ public bool TryAdvance(int bytes)
return false;
}

computedFlow = new FlowControlState(currentFlow.Available - (uint)bytes, currentFlow.IsAborted);
computedFlow = new FlowControlState(currentFlow.Available - (uint)bytes, isAborted: false);
} while (currentFlow._state != Interlocked.CompareExchange(ref _flow._state, computedFlow._state, currentFlow._state));

return true;
Expand All @@ -110,7 +110,7 @@ public bool TryUpdateWindow(int bytes, out int updateSize)
// It shouldn't be possible for the window size to ever exceed Http2PeerSettings.MaxWindowSize.
Debug.Assert(false, $"{nameof(TryUpdateWindow)} attempted to grow window past max size.");
}
computedFlow = new FlowControlState(currentFlow.Available + (uint)bytes, currentFlow.IsAborted);
computedFlow = new FlowControlState(currentFlow.Available + (uint)bytes, isAborted: false);
} while (currentFlow._state != Interlocked.CompareExchange(ref _flow._state, computedFlow._state, currentFlow._state));

if (_windowUpdatesDisabled)
Expand Down Expand Up @@ -156,7 +156,7 @@ public int Abort()
return 0;
}

computedFlow = new FlowControlState(currentFlow.Available, true);
computedFlow = new FlowControlState(currentFlow.Available, isAborted: true);
} while (currentFlow._state != Interlocked.CompareExchange(ref _flow._state, computedFlow._state, currentFlow._state));

// Tell caller to return connection window space consumed by this stream. Even if window updates have
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests.Http2.FlowControl;

public class InputFlowControlTests
{
private const int IterationCount = 1;

[Fact]
public async Task Threads1_Advance()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var sut = new InputFlowControl(5000, 1);
await Task.Run(() => Advance(sut)); ;
Expand All @@ -30,7 +32,7 @@ static void Advance(InputFlowControl sut)
[Fact]
public async Task Threads2_Advance()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var sut = new InputFlowControl(10000, 1);
var t1 = Task.Run(() => Advance(sut));
Expand All @@ -51,7 +53,7 @@ static void Advance(InputFlowControl sut)
[Fact]
public async Task Threads3_Advance()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var sut = new InputFlowControl(15000, 1);
var t1 = Task.Run(() => Advance(sut));
Expand All @@ -73,7 +75,7 @@ static void Advance(InputFlowControl sut)
[Fact]
public async Task Threads3_WindowUpdates()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var sut = new InputFlowControl(15000, 0);
var t1 = Task.Run(() => WindowUpdate(sut));
Expand All @@ -96,7 +98,7 @@ static void WindowUpdate(InputFlowControl sut)
[Fact]
public async Task Threads4_Advance()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var sut = new InputFlowControl(20000, 1);
var t1 = Task.Run(() => Advance(sut));
Expand All @@ -118,7 +120,7 @@ static void Advance(InputFlowControl sut)
[Fact]
public async Task Threads3_Abort()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var sut = new InputFlowControl(20000, 1);
var t1 = Task.Run(() => Advance(sut));
Expand Down Expand Up @@ -165,7 +167,7 @@ public void Abort_Abort()
[Fact]
public async Task Threads3Abort_AssertAfter()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var isAborted = false;
var sut = new InputFlowControl(90000, 1);
Expand Down Expand Up @@ -204,7 +206,7 @@ static void Advance(ref bool isAborted, InputFlowControl sut)
[Fact]
public async Task Threads3Abort_AssertBefore()
{
for (var i = 0; i < 3000; i++)
for (var i = 0; i < IterationCount; i++)
{
var isAborting = false;
var sut = new InputFlowControl(30000, 1);
Expand Down Expand Up @@ -243,7 +245,7 @@ static void Advance(ref bool isAborting, InputFlowControl sut)
[Fact]
public async Task Threads3WindowUpdates_AssertAfter()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var isAborted = false;
var sut = new InputFlowControl(90000, 1);
Expand Down Expand Up @@ -282,7 +284,7 @@ static void WindowUpdate(ref bool isAborted, InputFlowControl sut)
[Fact]
public async Task Threads3WindowUpdates_AssertBefore()
{
for (var i = 0; i < 3000; i++)
for (var i = 0; i < IterationCount; i++)
{
var isAborting = false;
var sut = new InputFlowControl(30000, 1);
Expand Down Expand Up @@ -321,7 +323,7 @@ static void WindowUpdate(ref bool isAborting, InputFlowControl sut)
[Fact]
public async Task Threads3Advance_WindowUpdates()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var sut = new InputFlowControl(30000, 0);
var t0 = Task.Run(() => WindowUpdate(sut));
Expand Down Expand Up @@ -354,7 +356,7 @@ static void Advance(InputFlowControl sut)
[Fact]
public async Task Threads3WindowUpdates_AssertSize()
{
for (var i = 0; i < 1000; i++)
for (var i = 0; i < IterationCount; i++)
{
var sizeSum = 0;
var sut = new InputFlowControl(15000, 10);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.FlowControl;

namespace Microsoft.AspNetCore.Server.Kestrel.Microbenchmarks.Http2.FlowControl;

public class FlowControlBenchmark
{
private readonly InputFlowControl _flowControl = new(1000, 10);
private const int N = 100000;
private const int Spin = 50;
private const int ThreadsCount = 3;

[IterationSetup]
public void IterationSetup()
{
_flowControl.Reset();
}

[Benchmark]
public async Task ThreadsAdvanceWithWindowUpdates()
{
var parallelThreads = new Task[ThreadsCount + 1];
_flowControl.Reset();
for (var i = 0; i < ThreadsCount; i++)
{
var advanceTask = Task.Factory.StartNew(() =>
{
for (int i = 0; i < N; i++)
{
if (_flowControl.TryUpdateWindow(16, out _))
{
for (int j = 0; j < Spin; j++)
{
}
}
}
}, TaskCreationOptions.LongRunning);
parallelThreads[i] = advanceTask;
var tAdvance = Task.Factory.StartNew(() =>
{
for (var i = 0; i < N; i++)
{
_flowControl.TryAdvance(1);
}
_flowControl.Abort();
}, TaskCreationOptions.LongRunning);
parallelThreads[ThreadsCount] = tAdvance;
}

await Task.WhenAll(parallelThreads);
}
}

This file was deleted.

0 comments on commit bfc2e12

Please sign in to comment.