Skip to content

Commit a8ce5e3

Browse files
committed
1.x: overhead reduction for merge and flatMap
1 parent 9bc1987 commit a8ce5e3

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

src/main/java/rx/internal/operators/OnSubscribeRange.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,16 @@ public void request(long n) {
7575
*/
7676
void slowpath(long r) {
7777
long idx = index;
78+
long e = 0L;
7879
while (true) {
7980
/*
8081
* This complicated logic is done to avoid touching the volatile `index` and `requested` values
8182
* during the loop itself. If they are touched during the loop the performance is impacted significantly.
8283
*/
8384
long fs = end - idx + 1;
84-
long e = Math.min(fs, r);
8585
final boolean complete = fs <= r;
8686

87-
fs = e + idx;
87+
fs = Math.min(fs, r) + idx;
8888
final Subscriber<? super Integer> o = this.o;
8989

9090
for (long i = idx; i != fs; i++) {
@@ -102,13 +102,19 @@ void slowpath(long r) {
102102
return;
103103
}
104104

105+
e -= fs - idx;
106+
105107
idx = fs;
106-
index = fs;
107108

108-
r = addAndGet(-e);
109+
r = get() + e;
109110
if (r == 0L) {
110-
// we're done emitting the number requested so return
111-
return;
111+
index = fs;
112+
r = addAndGet(e);
113+
if (r == 0L) {
114+
// we're done emitting the number requested so return
115+
return;
116+
}
117+
e = 0L;
112118
}
113119
}
114120
}
@@ -131,4 +137,4 @@ void fastpath() {
131137
}
132138
}
133139

134-
}
140+
}

src/main/java/rx/internal/operators/OperatorMerge.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,28 @@ static final class MergeSubscriber<T> extends Subscriber<Observable<? extends T>
177177
/** An empty array to avoid creating new empty arrays in removeInner. */
178178
static final InnerSubscriber<?>[] EMPTY = new InnerSubscriber<?>[0];
179179

180+
int scalarEmission;
181+
182+
final int scalarLimit;
183+
180184
public MergeSubscriber(Subscriber<? super T> child, boolean delayErrors, int maxConcurrent) {
181185
this.child = child;
182186
this.delayErrors = delayErrors;
183187
this.maxConcurrent = maxConcurrent;
184188
this.nl = NotificationLite.instance();
185189
this.innerGuard = new Object();
186190
this.innerSubscribers = EMPTY;
187-
request(maxConcurrent == Integer.MAX_VALUE ? Long.MAX_VALUE : maxConcurrent);
191+
long r;
192+
int lim;
193+
if (maxConcurrent == Integer.MAX_VALUE) {
194+
r = Long.MAX_VALUE;
195+
lim = Integer.MAX_VALUE;
196+
} else {
197+
r = maxConcurrent;
198+
lim = Math.max(maxConcurrent >> 1, 1);
199+
}
200+
this.scalarLimit = lim;
201+
request(r);
188202
}
189203

190204
Queue<Throwable> getOrCreateErrorQueue() {
@@ -488,7 +502,10 @@ protected void emitScalar(T value, long r) {
488502
if (r != Long.MAX_VALUE) {
489503
producer.produced(1);
490504
}
491-
this.requestMore(1);
505+
if (++scalarEmission == scalarLimit) {
506+
scalarEmission = 0;
507+
this.requestMore(scalarLimit);
508+
}
492509
// check if some state changed while emitting
493510
synchronized (this) {
494511
skipFinal = true;

0 commit comments

Comments
 (0)