From f3a7f3de732a2dc0bb91b1ae5e01545de553dbb4 Mon Sep 17 00:00:00 2001 From: akarnokd Date: Wed, 5 Feb 2014 23:14:44 +0100 Subject: [PATCH] CompositeSubscription performance increase --- .../subscriptions/CompositeSubscription.java | 30 +++++++++-- .../CompositeSubscriptionAddRemovePerf.java | 50 +++++++++++++++++++ 2 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 rxjava-core/src/perf/java/rx/subscriptions/CompositeSubscriptionAddRemovePerf.java diff --git a/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java b/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java index 834e0ea2bc..0c492bb861 100644 --- a/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java +++ b/rxjava-core/src/main/java/rx/subscriptions/CompositeSubscription.java @@ -57,19 +57,39 @@ State unsubscribe() { } State add(Subscription s) { - Subscription[] newSubscriptions = Arrays.copyOf(subscriptions, subscriptions.length + 1); - newSubscriptions[newSubscriptions.length - 1] = s; + int idx = subscriptions.length; + Subscription[] newSubscriptions = new Subscription[idx + 1]; + System.arraycopy(subscriptions, 0, newSubscriptions, 0, idx); + newSubscriptions[idx] = s; return new State(isUnsubscribed, newSubscriptions); } State remove(Subscription s) { - ArrayList newSubscriptions = new ArrayList(subscriptions.length); + if ((subscriptions.length == 1 && subscriptions[0].equals(s)) || subscriptions.length == 0) { + return clear(); + } + Subscription[] newSubscriptions = new Subscription[subscriptions.length - 1]; + int idx = 0; for (Subscription _s : subscriptions) { if (!_s.equals(s)) { - newSubscriptions.add(_s); + // was not in this composite + if (idx == subscriptions.length) { + return this; + } + newSubscriptions[idx] = _s; + idx++; } } - return new State(isUnsubscribed, newSubscriptions.toArray(new Subscription[newSubscriptions.size()])); + if (idx == 0) { + return clear(); + } + // subscription appeared more than once + if (idx < newSubscriptions.length) { + Subscription[] newSub2 = new Subscription[idx]; + System.arraycopy(newSubscriptions, 0, newSub2, 0, idx); + return new State(isUnsubscribed, newSub2); + } + return new State(isUnsubscribed, newSubscriptions); } State clear() { diff --git a/rxjava-core/src/perf/java/rx/subscriptions/CompositeSubscriptionAddRemovePerf.java b/rxjava-core/src/perf/java/rx/subscriptions/CompositeSubscriptionAddRemovePerf.java new file mode 100644 index 0000000000..e842fbc261 --- /dev/null +++ b/rxjava-core/src/perf/java/rx/subscriptions/CompositeSubscriptionAddRemovePerf.java @@ -0,0 +1,50 @@ + +package rx.subscriptions; + +import rx.perf.AbstractPerformanceTester; +import rx.util.functions.Action0; + +public class CompositeSubscriptionAddRemovePerf extends AbstractPerformanceTester { + public static void main(String[] args) { + final CompositeSubscriptionAddRemovePerf spt = new CompositeSubscriptionAddRemovePerf(); + try { + spt.runTest(new Action0() { + @Override + public void call() { + spt.timeAddAndRemove(); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + /** + * Test simple add + remove on a composite. + * + * With old Composite add/remove: + * + * Run: 10 - 14 985 141 ops/sec + * Run: 11 - 15 257 104 ops/sec + * Run: 12 - 14 797 996 ops/sec + * Run: 13 - 14 438 643 ops/sec + * Run: 14 - 14 985 864 ops/sec + * + * With optimized Composite add/remove: + * + * Run: 10 - 19 802 782 ops/sec + * Run: 11 - 18 896 021 ops/sec + * Run: 12 - 18 829 296 ops/sec + * Run: 13 - 19 729 876 ops/sec + * Run: 14 - 19 830 678 ops/sec + * + * about 32% increase + */ + void timeAddAndRemove() { + CompositeSubscription csub = new CompositeSubscription(); + BooleanSubscription bs = new BooleanSubscription(); + for (int i = 0; i < REPETITIONS; i++) { + csub.add(bs); + csub.remove(bs); + } + } +}