Optimize flatMapConcat for single element source, #25241#25242
Optimize flatMapConcat for single element source, #25241#25242
Conversation
|
Test FAILed. |
johanandren
left a comment
There was a problem hiding this comment.
Very nice numbers. Still a bit sad there isn't a way to make it more general though.
|
|
||
| "work with flatMapConcat optimized GraphStages.SingleSource" in assertAllStagesStopped { | ||
| Source(0 to 3) | ||
| .flatMapConcat(elem ⇒ new GraphStages.SingleSource(elem)) |
There was a problem hiding this comment.
Does this mean we should make the constructor of SingleSource a public API or we keep it to ourselves?
|
I found a way to grab the original
We could get an additional boost to 6743k ops/s by using the I also verified that the extra work doesn't introduce a regression for non single, see BEFORE AFTER |
|
Test PASSed. |
|
Pushed another change to take care of the case when there is no demand b4ea15e |
|
Test PASSed. |
| } | ||
|
|
||
| "find Source.single via TraversalBuilder" in assertAllStagesStopped { | ||
| TraversalBuilder.getSingleSource(Source.single("a")).get.elem should ===("a") |
There was a problem hiding this comment.
Check also that Source.single.{async/mapMatVal} causes a nested graph and does not match for extra measure? (Pretty sure they do, but just for extra measure.
There was a problem hiding this comment.
@johanandren Good point, it was wrong. Matched for those cases also. async is only adding attribute, and mapMaterializedValue is adding Transform traversal. Fixed with additional checks for those in 7ae02d1
* This first stab is only looking for `SingleSource` and note that `Source.single` is not returning that. Source.single has wrap with fromGraph and then the original `SingleSource` is lost.
b4ea15e to
7ae02d1
Compare
|
Test PASSed. |
| } | ||
|
|
||
| "find Source.single via TraversalBuilder" in assertAllStagesStopped { | ||
| TraversalBuilder.getSingleSource(Source.single("a")).get.elem should ===("a") |
| case _ ⇒ OptionVal.None | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Pyramid of optimization.
raboof
left a comment
There was a problem hiding this comment.
Sidesteps quite some ceremony in this case 👍
| var q: BufferImpl[SubSinkInlet[T]] = _ | ||
| // To be able to optimize for SingleSource without materializing them the queue may hold either | ||
| // SubSinkInlet[T] or SingleSource | ||
| var queue: BufferImpl[AnyRef] = _ |
| TraversalBuilder.getSingleSource(source.asInstanceOf[Graph[SourceShape[AnyRef], M]]) match { | ||
| case OptionVal.Some(single) ⇒ | ||
| if (isAvailable(out) && queue.isEmpty) { | ||
| push(out, single.elem.asInstanceOf[T]) |
| } | ||
|
|
||
| def removeSource(src: SubSinkInlet[T]): Unit = { | ||
| def removeSource(src: AnyRef): Unit = { |
There was a problem hiding this comment.
Maybe explicitly make it private? OK though.
SingleSourceand notethat
Source.singleis not returning that. Source.single haswrap with fromGraph and then the original
SingleSourceislost.
Refs #25241
Benchmark results speak for themselves, 287k vs 6641k elements/s: