spring-attic / reactive-streams-commons

A joint research effort for building highly optimized Reactive-Streams compliant operators.
Apache License 2.0
357 stars 51 forks source link

Design considerations #1

Closed akarnokd closed 8 years ago

akarnokd commented 8 years ago

There are a few decisions to be made:

1) Repo initialization with Gradle files and directories

Who should do this? I have a gradle setup I usually copy into new projects that can upload to maven based on local settings.

2) Rackage naming, structure

What should be the base package name. In addition, we may need an internal package.

3) Lock-free or not?

Most serializing operators can be implemented in both ways but lock-free usually requires lock-free queues (i.e., JCTools).

The project states it wants to avoid queue-use so we don't lock in on Disruptor or JCTools but is it possible to abstract away the queue operations, i.e., is the j.u.c.Queue interface an adequate abstraction?

We can also have implementations for both cases in separate subpackages lockfree and locking.

4) Which Java version?

Java 8 allows nicer code but Java 6 allows Android use.

5) Processor implementations

Do we want to provide these as well? Note that the operator redo - which unifies retry and repeat behavior through the signal of a Publisher requires a PublishProcessor at least (or a BehaviorProcessor at most), although these may be inlined.

6) Factory or classes

Should the library provide the operators via factory methods, i.e., Publisher<R> map(Publisher<T> source, Function<T, R> mapper); or as named classes: class PublisherMap<T, R>?

The latter case helps discovering what's in a chain.

7) Operator fusion

I'm in a relatively early stage of describing and prototyping operator fusion. What's definitely necessary is that each operator has a distinct class which also exposes its input parameters (i.e., the source and mapper in 6))

8) Beta/Experimental annotation

Do we want to copy the RxJava way of introducing new operators/classes?

9) Benchmarks

Do we want JMH benchmarks in the repo?

10) Reactive-Streams TCK

I have two problems with it: a) requires TestNG which is quite invasive in Eclipse and b) is designed to test either just and a replaying-type Processor implementation. It doesn't work properly for range for example because the test wants to verify if the output of the Publisher is the same as the test generated.

11) Optimizations vs Reactive-Streams spec

Certain internal operator optimizations, such as reusing a Subscriber instance, may violate the specification although completely safe to do.

The spec says that you can't subscribe the same instance multiple times to the same or different Publishers and some implementations may actually check for this (such as RxJavaReactiveStreams).

12) Inlining and API leaks

To avoid allocations, some operators may build upon existing classes or implement interfaces that leak into the API. For example, an auto-sharing operator PublisherAutoShare may extend AtomicInteger directly to save on an atomic counter field. However, this class now has a bunch of other methods that leaked in and requires extra care from the users

13) Building blocks

There are a few frequent building blocks useful for operators (i.e., arbiters, terminal atomics tools). Do we want to officially support them as well or keep them hidden in internal?

14) Field updaters, Atomic instances or Unsafe?

Which technique do we want? Note that Java 8 is about to receive performance optimizations targeting field updaters so they get very close to Unsafe.

smaldini commented 8 years ago

I think these questions are getting answered now but some might need more exploration :

11) Optimizations vs Reactive-Streams spec

Certain internal operator optimizations, such as reusing a Subscriber instance, may violate the specification although completely safe to do.

The spec says that you can't subscribe the same instance multiple times to the same or different Publishers and some implementations may actually check for this (such as RxJavaReactiveStreams).

12) Inlining and API leaks

To avoid allocations, some operators may build upon existing classes or implement interfaces that leak into the API. For example, an auto-sharing operator PublisherAutoShare may extend AtomicInteger directly to save on an atomic counter field. However, this class now has a bunch of other methods that leaked in and requires extra care from the users

But we can address them more naturally in separate issues if necessary.