Netflix/RxJava — pull request #1162 by kirkshoop (2014-05-06 15:10:25+00:00)
Title: fix to remove drift from schedulePeriodic

When implementing the 'worker' scheduler pattern in rxcpp I implemented schedulePeriodic differently because I predicted that the RxJava version would drift. Once the changes were working, I verified my prediction in rxcpp.

I decided to test the same in RxJava and contribute my approach.

This was my test:
``` java
import java.util.concurrent.TimeUnit;

import rx.Scheduler;
import rx.schedulers.Schedulers;
import rx.functions.Action0;

public class periodic {

public static void main(String[] args) {

final Scheduler scheduler = Schedulers.immediate();
final Scheduler.Worker w = scheduler.createWorker();

final long initial = TimeUnit.SECONDS.toMillis(2);
final long period = TimeUnit.SECONDS.toMillis(1);
final long start = scheduler.now() + initial;

w.schedulePeriodically(new Action0() {
long count = 0;
@Override
public void call() {
long tick = scheduler.now();
System.out.println(String.format("expected -> %dms, actual -> %dms, drift -> %dms", count*period, tick - start, tick - (start + (count*period))));
++count;
}
}, initial, period, TimeUnit.MILLISECONDS);
}

}
```
The existing impl causes this output:
```
$ java -cp rxjava-core/build/libs/rxjava-core-0.18.3-SNAPSHOT.jar:./ periodic
expected -> 0ms, actual -> 1ms, drift -> 1ms
expected -> 1000ms, actual -> 1002ms, drift -> 2ms
expected -> 2000ms, actual -> 2003ms, drift -> 3ms
expected -> 3000ms, actual -> 3004ms, drift -> 4ms
expected -> 4000ms, actual -> 4005ms, drift -> 5ms
expected -> 5000ms, actual -> 5006ms, drift -> 6ms
expected -> 6000ms, actual -> 6007ms, drift -> 7ms
expected -> 7000ms, actual -> 7008ms, drift -> 8ms
expected -> 8000ms, actual -> 8009ms, drift -> 9ms
expected -> 9000ms, actual -> 9010ms, drift -> 10ms
expected -> 10000ms, actual -> 10011ms, drift -> 11ms
expected -> 11000ms, actual -> 11012ms, drift -> 12ms
expected -> 12000ms, actual -> 12013ms, drift -> 13ms
expected -> 13000ms, actual -> 13014ms, drift -> 14ms
expected -> 14000ms, actual -> 14016ms, drift -> 16ms
expected -> 15000ms, actual -> 15017ms, drift -> 17ms
expected -> 16000ms, actual -> 16018ms, drift -> 18ms
expected -> 17000ms, actual -> 17019ms, drift -> 19ms
expected -> 18000ms, actual -> 18020ms, drift -> 20ms
expected -> 19000ms, actual -> 19021ms, drift -> 21ms
expected -> 20000ms, actual -> 20022ms, drift -> 22ms
expected -> 21000ms, actual -> 21023ms, drift -> 23ms
expected -> 22000ms, actual -> 22023ms, drift -> 23ms
expected -> 23000ms, actual -> 23024ms, drift -> 24ms
```
With this commit the test outputs:
```
$ java -cp ./:./rxjava-core/build/libs/rxjava-core-0.18.3-SNAPSHOT.jar periodic
expected -> 0ms, actual -> 3ms, drift -> 3ms
expected -> 1000ms, actual -> 1001ms, drift -> 1ms
expected -> 2000ms, actual -> 2001ms, drift -> 1ms
expected -> 3000ms, actual -> 3000ms, drift -> 0ms
expected -> 4000ms, actual -> 4001ms, drift -> 1ms
expected -> 5000ms, actual -> 5000ms, drift -> 0ms
expected -> 6000ms, actual -> 6000ms, drift -> 0ms
expected -> 7000ms, actual -> 7000ms, drift -> 0ms
expected -> 8000ms, actual -> 8001ms, drift -> 1ms
expected -> 9000ms, actual -> 9001ms, drift -> 1ms
expected -> 10000ms, actual -> 10001ms, drift -> 1ms
expected -> 11000ms, actual -> 11001ms, drift -> 1ms
expected -> 12000ms, actual -> 12001ms, drift -> 1ms
expected -> 13000ms, actual -> 13001ms, drift -> 1ms
expected -> 14000ms, actual -> 14001ms, drift -> 1ms
expected -> 15000ms, actual -> 15001ms, drift -> 1ms
expected -> 16000ms, actual -> 16001ms, drift -> 1ms
expected -> 17000ms, actual -> 17000ms, drift -> 0ms
expected -> 18000ms, actual -> 18000ms, drift -> 0ms
expected -> 19000ms, actual -> 19000ms, drift -> 0ms
expected -> 20000ms, actual -> 20000ms, drift -> 0ms
expected -> 21000ms, actual -> 21002ms, drift -> 2ms
expected -> 22000ms, actual -> 22000ms, drift -> 0ms
expected -> 23000ms, actual -> 23001ms, drift -> 1ms
expected -> 24000ms, actual -> 24001ms, drift -> 1ms
```