-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stream update 2.4.9 #2335
Merged
alexvaluyskiy
merged 22 commits into
akkadotnet:dev
from
marcpiechura:stream_update_2.4.9
Oct 15, 2016
Merged
Stream update 2.4.9 #2335
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
b361d2c
fix IllegalMonitorStateException in Source.queue
marcpiechura 389ec8b
make RunnableGraph.addAttributes return a RunnableGraph
marcpiechura cf87d40
json part 1
marcpiechura cf9bfe0
make Select a GraphStage
marcpiechura ce17fdf
optimize Aggregate supervision
marcpiechura abbdfcd
Microoptimizaitons in the interpreter
marcpiechura 98b5079
Event chasing implemented
marcpiechura c230a45
reducing array load pressure by making connections an explicit object
marcpiechura 64a01d2
Json part 2
marcpiechura 08c4cd6
Add FusedGraphBenchmark
marcpiechura 7ad9011
named should not replace all attributes
marcpiechura 21eb2a6
Merge grabs empty input
marcpiechura 26a6fd3
fix SinkSpec
marcpiechura 7a06174
Fixes for the JsonFraming stage
marcpiechura 552da98
Correctly handle parsing of JSON strings containing single quotes
marcpiechura 3927355
fix up docs for Sink
marcpiechura 1409ffc
Deprecate InvalidAbsorbTermination In favour of GraphStage
marcpiechura 23daaf2
Harden TickSourceSpec
marcpiechura 91212e4
Track pending requests properly on expectRequest
marcpiechura b80c87d
Add spec for failing tcp connection
marcpiechura e92e271
Balancer should not
marcpiechura bcf3cb2
spaces
marcpiechura File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
81 changes: 54 additions & 27 deletions
81
src/core/Akka.API.Tests/CoreAPISpec.ApproveStreams.approved.txt
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
328 changes: 328 additions & 0 deletions
328
src/core/Akka.Streams.Tests.Performance/FusedGraphsBenchmark.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,328 @@ | ||
using System; | ||
using System.Linq; | ||
using Akka.Actor; | ||
using Akka.Streams.Dsl; | ||
using Akka.Streams.Stage; | ||
using Akka.TestKit; | ||
using NBench; | ||
|
||
namespace Akka.Streams.Tests.Performance | ||
{ | ||
public class FusedGraphsBenchmark | ||
{ | ||
private const int ElementCount = 100 * 1000; | ||
|
||
private sealed class MutableElement | ||
{ | ||
public MutableElement(int value) | ||
{ | ||
Value = value; | ||
} | ||
|
||
public int Value { get; set; } | ||
} | ||
|
||
// Just to avoid allocations and still have a way to do some work in stages. The value itself does not matter | ||
// so no issues with sharing(the result does not make any sense, but hey) | ||
private sealed class TestSource : GraphStage<SourceShape<MutableElement>> | ||
{ | ||
private sealed class Logic : GraphStageLogic | ||
{ | ||
public Logic(TestSource stage) : base(stage.Shape) | ||
{ | ||
var left = ElementCount - 1; | ||
SetHandler(stage.Out, onPull: () => | ||
{ | ||
if (left >= 0) | ||
{ | ||
Push(stage.Out, stage._elements[left]); | ||
left--; | ||
} | ||
else | ||
CompleteStage(); | ||
}); | ||
} | ||
} | ||
|
||
private readonly MutableElement[] _elements; | ||
|
||
public TestSource(MutableElement[] elements) | ||
{ | ||
_elements = elements; | ||
|
||
Shape = new SourceShape<MutableElement>(Out); | ||
} | ||
|
||
private Outlet<MutableElement> Out { get; } = new Outlet<MutableElement>("TestSource.out"); | ||
|
||
public override SourceShape<MutableElement> Shape { get; } | ||
|
||
protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this); | ||
} | ||
|
||
private sealed class CompletionLatch : GraphStageWithMaterializedValue<SinkShape<MutableElement>, TestLatch> | ||
{ | ||
private sealed class Logic : GraphStageLogic | ||
{ | ||
private readonly CompletionLatch _stage; | ||
|
||
public Logic(CompletionLatch stage, TestLatch latch) : base(stage.Shape) | ||
{ | ||
_stage = stage; | ||
|
||
var sum = 0; | ||
SetHandler(stage.In, onPush: () => | ||
{ | ||
sum += Grab(stage.In).Value; | ||
Pull(stage.In); | ||
}, onUpstreamFinish: () => | ||
{ | ||
// Do not ignore work along the chain | ||
// on the jvm: | ||
// org.openjdk.jmh.infra.Blackhole.consume(sum) | ||
var i = 0; | ||
while (i != sum) | ||
sum--; | ||
|
||
latch.CountDown(); | ||
CompleteStage(); | ||
}); | ||
} | ||
|
||
public override void PreStart() => Pull(_stage.In); | ||
} | ||
|
||
public CompletionLatch() | ||
{ | ||
Shape = new SinkShape<MutableElement>(In); | ||
} | ||
|
||
private Inlet<MutableElement> In { get; } = new Inlet<MutableElement>("CompletionLatch.in"); | ||
|
||
public override SinkShape<MutableElement> Shape { get; } | ||
public override ILogicAndMaterializedValue<TestLatch> CreateLogicAndMaterializedValue(Attributes inheritedAttributes) | ||
{ | ||
var latch = new TestLatch(1); | ||
var logic = new Logic(this, latch); | ||
return new LogicAndMaterializedValue<TestLatch>(logic, latch); | ||
} | ||
} | ||
|
||
private sealed class IdentityStage : GraphStage<FlowShape<MutableElement, MutableElement>> | ||
{ | ||
private sealed class Logic : GraphStageLogic | ||
{ | ||
public Logic(IdentityStage stage) : base(stage.Shape) | ||
{ | ||
SetHandler(stage.In, onPush:()=>Push(stage.Out, Grab(stage.In))); | ||
SetHandler(stage.Out, onPull: () => Pull(stage.In)); | ||
} | ||
} | ||
|
||
public IdentityStage() | ||
{ | ||
Shape = new FlowShape<MutableElement, MutableElement>(In, Out); | ||
} | ||
|
||
private Outlet<MutableElement> Out { get; } = new Outlet<MutableElement>("IdentityStage.out"); | ||
|
||
private Inlet<MutableElement> In { get; } = new Inlet<MutableElement>("IdentityStage.in"); | ||
|
||
public override FlowShape<MutableElement, MutableElement> Shape { get; } | ||
|
||
protected override GraphStageLogic CreateLogic(Attributes inheritedAttributes) => new Logic(this); | ||
} | ||
|
||
private ActorSystem _system; | ||
private MutableElement[] _testElements; | ||
private ActorMaterializer _materializer; | ||
private RunnableGraph<TestLatch> _singleIdentity; | ||
private RunnableGraph<TestLatch> _chainOfIdentities; | ||
private RunnableGraph<TestLatch> _singleSelect; | ||
private RunnableGraph<TestLatch> _chainOfSelects; | ||
private RunnableGraph<TestLatch> _repeatTakeSelectAndAggregate; | ||
private RunnableGraph<TestLatch> _singleBuffer; | ||
private RunnableGraph<TestLatch> _chainOfBuffers; | ||
private RunnableGraph<TestLatch> _broadcastZip; | ||
private RunnableGraph<TestLatch> _balanceMerge; | ||
private RunnableGraph<TestLatch> _broadcastZipBalanceMerge; | ||
|
||
private static MutableElement Add(MutableElement x) | ||
{ | ||
x.Value++; | ||
return x; | ||
} | ||
|
||
private static RunnableGraph<TestLatch> Fuse(IRunnableGraph<TestLatch> graph) | ||
=> RunnableGraph.FromGraph(Fusing.Aggressive(graph)); | ||
|
||
[PerfSetup] | ||
public void Setup(BenchmarkContext context) | ||
{ | ||
_system = ActorSystem.Create("Test"); | ||
var settings = | ||
ActorMaterializerSettings.Create(_system) | ||
.WithFuzzingMode(false) | ||
.WithSyncProcessingLimit(int.MaxValue) | ||
.WithAutoFusing(false); // We fuse manually in this test in the setup | ||
|
||
_materializer = _system.Materializer(settings); | ||
_testElements = Enumerable.Repeat(0, ElementCount).Select(i => new MutableElement(i)).ToArray(); | ||
var testSource = Source.FromGraph(new TestSource(_testElements)); | ||
var testSink = Sink.FromGraph(new CompletionLatch()); | ||
var identityStage = new IdentityStage(); | ||
|
||
_singleIdentity = Fuse(testSource.Via(identityStage).ToMaterialized(testSink, Keep.Right)); | ||
_chainOfIdentities = | ||
Fuse( | ||
testSource.Via(identityStage) | ||
.Via(identityStage) | ||
.Via(identityStage) | ||
.Via(identityStage) | ||
.Via(identityStage) | ||
.Via(identityStage) | ||
.Via(identityStage) | ||
.Via(identityStage) | ||
.Via(identityStage) | ||
.Via(identityStage) | ||
.ToMaterialized(testSink, Keep.Right)); | ||
|
||
_singleSelect = Fuse(testSource.Select(Add).ToMaterialized(testSink, Keep.Right)); | ||
|
||
_chainOfSelects = Fuse( | ||
testSource.Select(Add) | ||
.Select(Add) | ||
.Select(Add) | ||
.Select(Add) | ||
.Select(Add) | ||
.Select(Add) | ||
.Select(Add) | ||
.Select(Add) | ||
.Select(Add) | ||
.Select(Add) | ||
.ToMaterialized(testSink, Keep.Right)); | ||
|
||
_repeatTakeSelectAndAggregate = | ||
Fuse(Source.Repeat(new MutableElement(0)) | ||
.Take(ElementCount) | ||
.Select(Add) | ||
.Select(Add) | ||
.Aggregate(new MutableElement(0), (acc, x) => | ||
{ | ||
acc.Value += x.Value; | ||
return acc; | ||
}).ToMaterialized(testSink, Keep.Right)); | ||
|
||
_singleBuffer = | ||
Fuse(testSource.Buffer(10, OverflowStrategy.Backpressure).ToMaterialized(testSink, Keep.Right)); | ||
|
||
_chainOfBuffers = | ||
Fuse( | ||
testSource.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.Buffer(10, OverflowStrategy.Backpressure) | ||
.ToMaterialized(testSink, Keep.Right)); | ||
|
||
var broadcastZipFLow = Flow.FromGraph(GraphDsl.Create(b => | ||
{ | ||
var bcast = b.Add(new Broadcast<MutableElement>(2)); | ||
var zip = b.Add(new Zip<MutableElement, MutableElement>()); | ||
|
||
b.From(bcast).To(zip.In0); | ||
b.From(bcast).To(zip.In1); | ||
var outlet = | ||
b.From(zip.Out).Via(Flow.Create<Tuple<MutableElement, MutableElement>>().Select(t => t.Item1)); | ||
return new FlowShape<MutableElement, MutableElement>(bcast.In, outlet.Out); | ||
})); | ||
|
||
var balanceMergeFlow = Flow.FromGraph(GraphDsl.Create(b => | ||
{ | ||
var balance = b.Add(new Balance<MutableElement>(2)); | ||
var merge = b.Add(new Merge<MutableElement>(2)); | ||
|
||
b.From(balance).To(merge); | ||
b.From(balance).To(merge); | ||
|
||
return new FlowShape<MutableElement, MutableElement>(balance.In, merge.Out); | ||
})); | ||
|
||
_broadcastZip = Fuse(testSource.Via(broadcastZipFLow).ToMaterialized(testSink, Keep.Right)); | ||
|
||
_balanceMerge = Fuse(testSource.Via(balanceMergeFlow).ToMaterialized(testSink, Keep.Right)); | ||
|
||
_broadcastZipBalanceMerge = Fuse(testSource.Via(broadcastZipFLow).Via(balanceMergeFlow).ToMaterialized(testSink, Keep.Right)); | ||
} | ||
|
||
[PerfCleanup] | ||
public void Cleanup() => _system.Terminate().Wait(TimeSpan.FromSeconds(10)); | ||
|
||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 50)] | ||
public void SingleIdentity() => _singleIdentity.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 100)] | ||
public void ChainOfIdentities() => _chainOfIdentities.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 50)] | ||
public void SingleSelect() => _singleSelect.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 110)] | ||
public void ChainOfSelects() => _chainOfSelects.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 60)] | ||
public void SingleBuffer() => _singleBuffer.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 350)] | ||
public void ChainOfBuffers() => _chainOfBuffers.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 3500)] | ||
public void RepeatTakeSelectAndAggregate() => _repeatTakeSelectAndAggregate.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 100)] | ||
public void BroadcastZip() => _broadcastZip.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 50)] | ||
public void BalanceMerge() => _balanceMerge.Run(_materializer).Ready(); | ||
|
||
|
||
[PerfBenchmark(RunMode = RunMode.Iterations, TestMode = TestMode.Test, NumberOfIterations = 3)] | ||
[TimingMeasurement] | ||
[ElapsedTimeAssertion(MaxTimeMilliseconds = 100)] | ||
public void BroadcastZipBalanceMerge() => _broadcastZipBalanceMerge.Run(_materializer).Ready(); | ||
|
||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why you need private property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For running this stream.