Netflix/RxJava — pull request #835 by benjchristensen (2014-02-07 07:48:32+00:00)
Title: ObserveOn Operator with Backpressure

This is a re-implementation of ObserveOn done for 3 purposes:

1) Migrate to new `lift` style so the `Subscription` flows through correctly
2) Eliminate the wasted first schedule step (reported by @mttkay https://github.com/Netflix/RxJava/pull/797#issuecomment-34044956)
3) Eliminate buffering so it naturally provides back pressure

Unit tests are passing on my machine for a full build, but I'm interested in user experience, particularly from Android users where `observeOn` behavior is mission critical.

This WILL change behavior and possibly cause problems if `observeOn` was being used to make something async (which is not the purpose of `observeOn`. The `subscribeOn` operator is the one to use for making something async.

This is a complete re-write so I may very well have created nasty bugs that we don't yet have unit tests for so I'd appreciate a thorough review and testing.

One possible concern is performance. In the case of a synchronous firehose (not the normal use case, but a use case nonetheless), this is far slower because now each `onNext` is sent one-at-a-time across thread boundaries whereas before it would put everything into a queue on one side then read it all from the queue on the other side.

Thus, for this code that synchronously firehoses 100000 values it is about 7 times faster on the current code without back-pressure:
```java
long last = Observable.range(0, 100000).observeOn(Schedulers.newThread()).toBlockingObservable().last();
```

However, this code is the same performance:

```java
long last = Observable.interval(1, TimeUnit.MILLISECONDS).take(1000).observeOn(Schedulers.newThread()).toBlockingObservable().last();
```

The difference being that we're not just filling up the queue in the second one as it has latency.

I believe this is okay as the intent of `observeOn` is moving across thread boundaries, such as for UI events, and eliminating the bad behavior of buffer-bloat is the right thing.

I'm sure we can find some performance improvements in this code, but it's worth pointing out how the change in behavior can affect it.