ekmett / machines

Networks of composable stream transducers
Other
339 stars 46 forks source link

Add more benchmarks and improve performance #91

Closed harendra-kumar closed 6 years ago

harendra-kumar commented 7 years ago

Significant changes include:

1) Added comparison with "streaming" package which seems to be better than pipes and conduit in most cases. 2) Added benchmarks to compare toList APIs 3) Added a composite benchmark to measure performance when multiple ops are composed together 4) Added benchmarks to measure perf in the IO monad. 5) Improve performance of toList and the composite benchmarks by inlining runT and runT_

The inlining change made the toList benchmarks at par or better than others. It improved the composite benchmarks as well quite a bit but they are still worse off than other packages. Especially the IO monad case (CompositeIO benchmark) seems to be pretty bad - streaming takes 46 ms whereas machines takes 313 ms.

harendra-kumar commented 7 years ago

It seems even though machines is good at micro-benchmarks it does not fair well with multiple composed operations. I added multiple benchmarks to measure different aspects of composition to figure out the problem. Here are the results of some of the benchmarks where machines is not doing well. If anyone has a clue about the problem please let me know. One thing could be that other packages use rewrite rules which can fuse multiple ops together creating a more efficient code.

Measures four filters chained together passing everything as is. machines is slower than streaming but not a lot.

benchmarking compose/summary/machines
time                 109.7 ms   (105.8 ms .. 113.4 ms)
benchmarking compose/summary/streaming
time                 71.19 ms   (67.87 ms .. 73.76 ms)

The same as above but in IO monad. Not sure why streaming is so much faster than machines. Is there something wrong with the benchmark? Conduit is also pretty fast.

benchmarking compose/summary-io/machines
time                 230.7 ms   (222.3 ms .. 237.8 ms)
benchmarking compose/summary-io/streaming
time                 4.901 ms   (4.525 ms .. 5.394 ms)
benchmarking compose/summary-io/conduit
time                 36.84 ms   (36.43 ms .. 37.19 ms)

This one composes map and filter operations alternately. Again streaming is quite a bit faster.

benchmarking compose/summary-alternate/machines
time                 274.5 ms   (271.5 ms .. 280.6 ms)
benchmarking compose/summary-alternate/streaming
time                 204.3 ms   (192.4 ms .. 214.0 ms)

This one filters out all stream elements (empties the stream) in the first stage and then composes three more filters in the next stages which should essentially be doing nothing.

benchmarking compose/summary-filter-effect/machines
time                 72.81 ms   (70.63 ms .. 76.51 ms)
benchmarking compose/summary-filter-effect/conduit
time                 17.78 ms   (16.85 ms .. 18.83 ms)

The same as above but in the IO monad. Looks like streaming is doing nothing. Is that fusion at work? Even pipe and conduit have similar results.

benchmarking compose/summary-filter-effect-io/machines
time                 117.3 ms   (115.7 ms .. 118.4 ms)
benchmarking compose/summary-filter-effect-io/streaming
time                 2.467 ns   (2.444 ns .. 2.487 ns)

This benchmark measures conversion of the stream to a list. Others are twice as fast as machines.

benchmarking toList/machines
time                 6.041 ms   (5.844 ms .. 6.226 ms)
benchmarking toList/conduit
time                 3.291 ms   (3.130 ms .. 3.519 ms)
harendra-kumar commented 7 years ago

One of the travis CI tests failed due to a cabal-install error:

$ cabal install --only-dependencies --enable-tests --dry -v > installplan.txt
cabal: internal error when reading package index: failed to parse .cabal
fileThe package index or index cache is probably corrupt. Running cabal update
might fix it.
YoEight commented 6 years ago

Thanks for your contribution, sorry for the long delay.