Reactive Slick

Here's the ongoing work on Reactive Slick.

/cc @cvogt for review later
On Sat, Dec 13, 2014 at 12:09 AM, Stefan Zeiger <notifications@github.com>
wrote:

> In src/main/scala/scala/slick/backend/DatabaseComponent.scala
> <https://github.com/slick/slick/pull/1021#discussion-diff-21779824>:
>
> > +      if(s ne null) {
> > +        streamState = null
> > +        if(streamLogger.isDebugEnabled) streamLogger.debug("Scheduling stream continuation after transition from demand = 0")
> > +        val a = streamingAction
> > +        database.scheduleSynchronousStreaming(a, this)(s.asInstanceOf[a.StreamState])
> > +      } else {
> > +        if(streamLogger.isDebugEnabled) streamLogger.debug("Saw transition from demand = 0, but no stream continuation available")
> > +      }
> > +    }
> > +
> > +    ////////////////////////////////////////////////////////////////////////// Subscription methods
> > +
> > +    def request(l: Long): Unit = if(!cancelRequested) {
> > +      if(l <= 0)
> > +        throw new IllegalArgumentException("Requested count must not be <= 0 (see Reactive Streams spec, 3.9)")
> > +      else if(requested + l < 0) {
>
> The TCK doesn't test this scenario. Otherwise this test would have to fail
> for the current implementation here.
>
> You don't need a memory barrier between individual elements in a batch
> because you call onNext synchronously. If the Subscriber wants to process
> the signals asynchronously, it is his responsibility to publish them
> properly.
>
What the spec essentially says is that the -is- an async boundary between
components, and sync handoffs are only allowed if they "cannot be
detected".

> With database I/O, I doubt that it makes much of a difference for the
> performance, but in a micro benchmark (
> https://gist.github.com/szeiger/b4ab7a6fff469be91967) the effect is *very*
> noticeable (with Java 7 on my MBP, after some warm-up cycles):
>
> [info] Local          : 30ms
> [info] Local Counting : 59ms
> [info] Atomic Counting: 1034ms
>
> Processing demand asynchronously would require a different (i.e. less
> efficient) synchronization scheme than the single AtomicLong that I use at
> the moment. Keeping two different counts is indeed what the current
> implementation does but the requested count is only touched in request()
> and it doesn't need any synchronization.
>
Sorry for being overly vague, I meant benchmarking full RS implementations
using either of the versions of the spec (current and proposed).

The idea for RS is to allow to go outside of lockstep processing by
increasing the demand, and we have measured performance > 100 million
onNexts per second with the correct decoupling between consumer and
producer. @rkuhn should be able to say more.

That aside, I can definitely recommend to use JMH for benchmarking so you
are sure that it's "by the book".

One idea is that you keep track of the Slick publishers and subscribers,
and optimize if you see a slick subscriber being subscribed to a slick
producer.

> —
> Reply to this email directly or view it on GitHub
> <https://github.com/slick/slick/pull/1021/files#r21779824>.
>



-- 
Cheers,
√