iteratee icon indicating copy to clipboard operation
iteratee copied to clipboard

Add Monix observable to benchmarks

Open rossabaker opened this issue 9 years ago • 7 comments

rossabaker avatar Sep 23 '16 21:09 rossabaker

/cc @alexandru for sanity check of implementation

My results:

[info] Benchmark                      Mode  Cnt      Score     Error  Units
[info] InMemoryBenchmark.sumInts0II  thrpt   20  11818.266 ± 209.216  ops/s
[info] InMemoryBenchmark.sumInts1IM  thrpt   20  11321.185 ± 234.467  ops/s
[info] InMemoryBenchmark.sumInts2IT  thrpt   20  11081.743 ± 286.743  ops/s
[info] InMemoryBenchmark.sumInts3IR  thrpt   20  17495.544 ± 247.070  ops/s
[info] InMemoryBenchmark.sumInts4S   thrpt   20     61.534 ±   1.340  ops/s
[info] InMemoryBenchmark.sumInts5Z   thrpt   20    260.992 ±   5.877  ops/s
[info] InMemoryBenchmark.sumInts6P   thrpt   20     42.504 ±   2.216  ops/s
[info] InMemoryBenchmark.sumInts7C   thrpt   20  11856.072 ± 279.998  ops/s
[info] InMemoryBenchmark.sumInts8F   thrpt   20   9149.361 ± 231.823  ops/s
[info] InMemoryBenchmark.sumInts9M   thrpt   20  11971.040 ±  61.548  ops/s
[info] Benchmark                         Mode  Cnt     Score     Error  Units
[info] StreamingBenchmark.takeLongs0II  thrpt   20  1966.850 ±  62.115  ops/s
[info] StreamingBenchmark.takeLongs1IM  thrpt   20  1418.263 ±  29.080  ops/s
[info] StreamingBenchmark.takeLongs2IT  thrpt   20   909.093 ±  24.607  ops/s
[info] StreamingBenchmark.takeLongs3IR  thrpt   20   753.946 ±  31.057  ops/s
[info] StreamingBenchmark.takeLongs4S   thrpt   20    50.867 ±   1.586  ops/s
[info] StreamingBenchmark.takeLongs5Z   thrpt   20   160.428 ±   4.338  ops/s
[info] StreamingBenchmark.takeLongs6P   thrpt   20     1.324 ±   0.162  ops/s
[info] StreamingBenchmark.takeLongs7C   thrpt   20  2910.949 ±  40.390  ops/s
[info] StreamingBenchmark.takeLongs8F   thrpt   20     5.603 ±   0.136  ops/s
[info] StreamingBenchmark.takeLongs9M   thrpt   20  4439.064 ± 190.045  ops/s

rossabaker avatar Sep 23 '16 21:09 rossabaker

Thanks, @rossabaker! (although I'm not sure the mutable VectorBuilder is 100% fair here).

travisbrown avatar Sep 23 '16 22:09 travisbrown

Neither am I. I got the idea from https://github.com/monixio/monix/issues/185. I can't put my finger on how it might leak, but mutability without conplete understanding makes me nervous.

Redefining fs2's runLog with a VectorBuilder brings takeLongs8F to 6.66 ops/s. Also squeamish about that.

rossabaker avatar Sep 23 '16 22:09 rossabaker

@rossabaker If that's the most idiomatic way of writing the observable computation, I guess it could stand, but I mostly just don't want the benchmark to be measuring the technique used for concatenating vectors.

travisbrown avatar Sep 23 '16 22:09 travisbrown

I imagine the collection version is also using a VectorBuilder. I tried and failed to prove this by reasoning about CanBuildFrom. I think we're measuring that Monix beats scala.Stream in this benchmark by not memoizing, but this is my very first Observable. Idiomatic may be better judged by @alexandru .

rossabaker avatar Sep 24 '16 01:09 rossabaker

Hi guys, I just saw this.

The samples are fine, the foldLeftF operation takes the seed as a lazy parameter that's initialized on each evaluation of that Observable, so the mutation is controlled. We use this trick in toListL as well, building a List by means of a ListBuffer. It's also what CanBuildFrom does from my understanding.

The Observable you're seeing here is indeed more efficient than a Scala Stream because of the underlying model, being push-based, which makes certain operations extremely efficient. Where it tends to start losing is when concurrency gets involved. Memoization of an observable for example will be less efficient on the first pass through a stream, because it has to allow new subscribers at any point without losing events, so subscribe() ends up being concurrent with the (push-based) data source.

Btw, a good benchmark related to streaming should measure flatMap. This is another example where you'll see Observable losing some steam, because again, flatMap in Observable requires some concurrency handling, having overhead related to juggling with atomic references. Given the constraints, it does a good job, but a pull-based model (like Scala's Stream) should beat it easily.

alexandru avatar Sep 25 '16 07:09 alexandru

Codecov Report

Merging #132 into master will decrease coverage by 0.11%. The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #132      +/-   ##
==========================================
- Coverage   97.64%   97.53%   -0.12%     
==========================================
  Files          24       24              
  Lines         892      891       -1     
  Branches       60       60              
==========================================
- Hits          871      869       -2     
- Misses         21       22       +1
Impacted Files Coverage Δ
.../src/main/scala/io/iteratee/monix/TaskModule.scala 0% <0%> (-50%) :arrow_down:
core/src/main/scala/io/iteratee/Enumeratee.scala 99.53% <0%> (-0.47%) :arrow_down:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 6a9aeb7...7e846b5. Read the comment docs.

codecov-io avatar Dec 19 '17 13:12 codecov-io