Skip to content

Commit f3a7f3d

Browse files
akarnokdakarnokd
authored andcommitted
CompositeSubscription performance increase
1 parent d4a0e7e commit f3a7f3d

File tree

2 files changed

+75
-5
lines changed

2 files changed

+75
-5
lines changed

rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,39 @@ State unsubscribe() {
5757
}
5858

5959
State add(Subscription s) {
60-
Subscription[] newSubscriptions = Arrays.copyOf(subscriptions, subscriptions.length + 1);
61-
newSubscriptions[newSubscriptions.length - 1] = s;
60+
int idx = subscriptions.length;
61+
Subscription[] newSubscriptions = new Subscription[idx + 1];
62+
System.arraycopy(subscriptions, 0, newSubscriptions, 0, idx);
63+
newSubscriptions[idx] = s;
6264
return new State(isUnsubscribed, newSubscriptions);
6365
}
6466

6567
State remove(Subscription s) {
66-
ArrayList<Subscription> newSubscriptions = new ArrayList<Subscription>(subscriptions.length);
68+
if ((subscriptions.length == 1 && subscriptions[0].equals(s)) || subscriptions.length == 0) {
69+
return clear();
70+
}
71+
Subscription[] newSubscriptions = new Subscription[subscriptions.length - 1];
72+
int idx = 0;
6773
for (Subscription _s : subscriptions) {
6874
if (!_s.equals(s)) {
69-
newSubscriptions.add(_s);
75+
// was not in this composite
76+
if (idx == subscriptions.length) {
77+
return this;
78+
}
79+
newSubscriptions[idx] = _s;
80+
idx++;
7081
}
7182
}
72-
return new State(isUnsubscribed, newSubscriptions.toArray(new Subscription[newSubscriptions.size()]));
83+
if (idx == 0) {
84+
return clear();
85+
}
86+
// subscription appeared more than once
87+
if (idx < newSubscriptions.length) {
88+
Subscription[] newSub2 = new Subscription[idx];
89+
System.arraycopy(newSubscriptions, 0, newSub2, 0, idx);
90+
return new State(isUnsubscribed, newSub2);
91+
}
92+
return new State(isUnsubscribed, newSubscriptions);
7393
}
7494

7595
State clear() {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
package rx.subscriptions;
3+
4+
import rx.perf.AbstractPerformanceTester;
5+
import rx.util.functions.Action0;
6+
7+
public class CompositeSubscriptionAddRemovePerf extends AbstractPerformanceTester {
8+
public static void main(String[] args) {
9+
final CompositeSubscriptionAddRemovePerf spt = new CompositeSubscriptionAddRemovePerf();
10+
try {
11+
spt.runTest(new Action0() {
12+
@Override
13+
public void call() {
14+
spt.timeAddAndRemove();
15+
}
16+
});
17+
} catch (Exception e) {
18+
e.printStackTrace();
19+
}
20+
}
21+
/**
22+
* Test simple add + remove on a composite.
23+
*
24+
* With old Composite add/remove:
25+
*
26+
* Run: 10 - 14 985 141 ops/sec
27+
* Run: 11 - 15 257 104 ops/sec
28+
* Run: 12 - 14 797 996 ops/sec
29+
* Run: 13 - 14 438 643 ops/sec
30+
* Run: 14 - 14 985 864 ops/sec
31+
*
32+
* With optimized Composite add/remove:
33+
*
34+
* Run: 10 - 19 802 782 ops/sec
35+
* Run: 11 - 18 896 021 ops/sec
36+
* Run: 12 - 18 829 296 ops/sec
37+
* Run: 13 - 19 729 876 ops/sec
38+
* Run: 14 - 19 830 678 ops/sec
39+
*
40+
* about 32% increase
41+
*/
42+
void timeAddAndRemove() {
43+
CompositeSubscription csub = new CompositeSubscription();
44+
BooleanSubscription bs = new BooleanSubscription();
45+
for (int i = 0; i < REPETITIONS; i++) {
46+
csub.add(bs);
47+
csub.remove(bs);
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)