diff options
| author | 2022-09-23 19:43:52 +0800 | |
|---|---|---|
| committer | 2022-09-23 19:47:19 +0800 | |
| commit | 06b6689d8d885475db558d87359f2b52ee6b5247 (patch) | |
| tree | 08034abfdc2f1697903b69a29c65644d381fdf6f | |
| parent | 112acdd7fd1735ae450786f7bdea57aef3aa6f56 (diff) | |
Remove unused pooled lambda methods
Those methods have not been used for a long time. And the
regular lambda is already good in performance.
Also fix the test:
- Log pattern in new platform is changed.
(need to append "/data/anr/" manually)
- Format line endings.
Bug: 120160274
Test: atest LambdaPerfTest
Change-Id: I761fc3a75a3c740a530b8e377b67afd5decb5503
| -rwxr-xr-x | core/java/com/android/internal/util/function/pooled/PooledLambda.java | 501 | ||||
| -rw-r--r-- | tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java | 912 |
2 files changed, 458 insertions, 955 deletions
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java index f073c1c046c5..2bfde242a987 100755 --- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java +++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java @@ -22,36 +22,24 @@ import static com.android.internal.util.function.pooled.PooledLambdaImpl.acquire import android.os.Message; import com.android.internal.util.function.DecConsumer; -import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.DodecConsumer; -import com.android.internal.util.function.DodecFunction; import com.android.internal.util.function.HeptConsumer; -import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexConsumer; -import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.NonaConsumer; -import com.android.internal.util.function.NonaFunction; import com.android.internal.util.function.OctConsumer; -import com.android.internal.util.function.OctFunction; import com.android.internal.util.function.QuadConsumer; -import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuadPredicate; import com.android.internal.util.function.QuintConsumer; -import com.android.internal.util.function.QuintFunction; import com.android.internal.util.function.QuintPredicate; import com.android.internal.util.function.TriConsumer; -import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.TriPredicate; import com.android.internal.util.function.UndecConsumer; -import com.android.internal.util.function.UndecFunction; import com.android.internal.util.function.pooled.PooledLambdaImpl.LambdaType.ReturnType; import java.util.function.BiConsumer; -import java.util.function.BiFunction; import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Predicate; import java.util.function.Supplier; /** @@ -194,40 +182,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1) } - */ - static <A> PooledSupplier<Boolean> obtainSupplier( - Predicate<? super A> function, - A arg1) { - return acquire(PooledLambdaImpl.sPool, - function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null, null, - null, null, null, null); - } - - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1) } - */ - static <A, R> PooledSupplier<R> obtainSupplier( - Function<? super A, ? extends R> function, - A arg1) { - return acquire(PooledLambdaImpl.sPool, - function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null, null, - null, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -279,42 +233,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2) } - */ - static <A, B> PooledSupplier<Boolean> obtainSupplier( - BiPredicate<? super A, ? super B> function, - A arg1, B arg2) { - return acquire(PooledLambdaImpl.sPool, - function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null, - null, null, null, null); - } - - /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2) } - */ - static <A, B, R> PooledSupplier<R> obtainSupplier( - BiFunction<? super A, ? super B, ? extends R> function, - A arg1, B arg2) { - return acquire(PooledLambdaImpl.sPool, - function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -411,24 +329,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 placeholder for a missing argument. Use {@link #__} to get one - * @param arg2 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg1) -> function(arg1, arg2) } - */ - static <A, B, R> PooledFunction<A, R> obtainFunction( - BiFunction<? super A, ? super B, ? extends R> function, - ArgumentPlaceholder<A> arg1, B arg2) { - return acquire(PooledLambdaImpl.sPool, - function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -465,24 +365,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 placeholder for a missing argument. Use {@link #__} to get one - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg2) -> function(arg1, arg2) } - */ - static <A, B, R> PooledFunction<B, R> obtainFunction( - BiFunction<? super A, ? super B, ? extends R> function, - A arg1, ArgumentPlaceholder<B> arg2) { - return acquire(PooledLambdaImpl.sPool, - function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null, - null, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -536,25 +418,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3) } - */ - static <A, B, C, R> PooledSupplier<R> obtainSupplier( - TriFunction<? super A, ? super B, ? super C, ? extends R> function, - A arg1, B arg2, C arg3) { - return acquire(PooledLambdaImpl.sPool, - function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -574,25 +437,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 placeholder for a missing argument. Use {@link #__} to get one - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg1) -> function(arg1, arg2, arg3) } - */ - static <A, B, C, R> PooledFunction<A, R> obtainFunction( - TriFunction<? super A, ? super B, ? super C, ? extends R> function, - ArgumentPlaceholder<A> arg1, B arg2, C arg3) { - return acquire(PooledLambdaImpl.sPool, - function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -612,25 +456,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 placeholder for a missing argument. Use {@link #__} to get one - * @param arg3 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg2) -> function(arg1, arg2, arg3) } - */ - static <A, B, C, R> PooledFunction<B, R> obtainFunction( - TriFunction<? super A, ? super B, ? super C, ? extends R> function, - A arg1, ArgumentPlaceholder<B> arg2, C arg3) { - return acquire(PooledLambdaImpl.sPool, - function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -650,25 +475,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 placeholder for a missing argument. Use {@link #__} to get one - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg3) -> function(arg1, arg2, arg3) } - */ - static <A, B, C, R> PooledFunction<C, R> obtainFunction( - TriFunction<? super A, ? super B, ? super C, ? extends R> function, - A arg1, B arg2, ArgumentPlaceholder<C> arg3) { - return acquire(PooledLambdaImpl.sPool, - function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null, - null, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -724,26 +530,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4) } - */ - static <A, B, C, D, R> PooledSupplier<R> obtainSupplier( - QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function, - A arg1, B arg2, C arg3, D arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -764,26 +550,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 placeholder for a missing argument. Use {@link #__} to get one - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg1) -> function(arg1, arg2, arg3, arg4) } - */ - static <A, B, C, D, R> PooledFunction<A, R> obtainFunction( - QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function, - ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -804,26 +570,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 placeholder for a missing argument. Use {@link #__} to get one - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg2) -> function(arg1, arg2, arg3, arg4) } - */ - static <A, B, C, D, R> PooledFunction<B, R> obtainFunction( - QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function, - A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -844,26 +590,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 placeholder for a missing argument. Use {@link #__} to get one - * @param arg4 parameter supplied to {@code function} on call - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg3) -> function(arg1, arg2, arg3, arg4) } - */ - static <A, B, C, D, R> PooledFunction<C, R> obtainFunction( - QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function, - A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - - /** * {@link PooledConsumer} factory * * @param function non-capturing lambda(typically an unbounded method reference) @@ -884,26 +610,6 @@ public interface PooledLambda { } /** - * {@link PooledFunction} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 placeholder for a missing argument. Use {@link #__} to get one - * @return a {@link PooledFunction}, equivalent to lambda: - * {@code (arg4) -> function(arg1, arg2, arg3, arg4) } - */ - static <A, B, C, D, R> PooledFunction<D, R> obtainFunction( - QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function, - A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) { - return acquire(PooledLambdaImpl.sPool, - function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null, - null, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -961,27 +667,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5) } - */ - static <A, B, C, D, E, R> PooledSupplier<R> obtainSupplier( - QuintFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? extends R> - function, A arg1, B arg2, C arg3, D arg4, E arg5) { - return acquire(PooledLambdaImpl.sPool, - function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null, null, - null, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -1042,28 +727,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6) } - */ - static <A, B, C, D, E, F, R> PooledSupplier<R> obtainSupplier( - HexFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, - ? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) { - return acquire(PooledLambdaImpl.sPool, - function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null, null, - null, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -1126,30 +789,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7) } - */ - static <A, B, C, D, E, F, G, R> PooledSupplier<R> obtainSupplier( - HeptFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, - ? super G, ? extends R> function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) { - return acquire(PooledLambdaImpl.sPool, - function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null, - null, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -1215,31 +854,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) } - */ - static <A, B, C, D, E, F, G, H, R> PooledSupplier<R> obtainSupplier( - OctFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, - ? super G, ? super H, ? extends R> function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8) { - return acquire(PooledLambdaImpl.sPool, - function, 8, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - null, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -1308,32 +922,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @param arg9 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) } - */ - static <A, B, C, D, E, F, G, H, I, R> PooledSupplier<R> obtainSupplier( - NonaFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, - ? super G, ? super H, ? super I, ? extends R> function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9) { - return acquire(PooledLambdaImpl.sPool, - function, 9, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - arg9, null, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -1404,33 +992,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @param arg9 parameter supplied to {@code function} on call - * @param arg10 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) } - */ - static <A, B, C, D, E, F, G, H, I, J, R> PooledSupplier<R> obtainSupplier( - DecFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, - ? super G, ? super H, ? super I, ? super J, ? extends R> function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) { - return acquire(PooledLambdaImpl.sPool, - function, 10, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - arg9, arg10, null, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -1504,36 +1065,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @param arg9 parameter supplied to {@code function} on call - * @param arg10 parameter supplied to {@code function} on call - * @param arg11 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, - * arg11) } - */ - static <A, B, C, D, E, F, G, H, I, J, K, R> PooledSupplier<R> obtainSupplier( - UndecFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, - ? super G, ? super H, ? super I, ? super J, ? super K, ? extends R> function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, - K arg11) { - return acquire(PooledLambdaImpl.sPool, - function, 11, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - arg9, arg10, arg11, null); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. @@ -1611,38 +1142,6 @@ public interface PooledLambda { } /** - * {@link PooledSupplier} factory - * - * @param function non-capturing lambda(typically an unbounded method reference) - * to be invoked on call - * @param arg1 parameter supplied to {@code function} on call - * @param arg2 parameter supplied to {@code function} on call - * @param arg3 parameter supplied to {@code function} on call - * @param arg4 parameter supplied to {@code function} on call - * @param arg5 parameter supplied to {@code function} on call - * @param arg6 parameter supplied to {@code function} on call - * @param arg7 parameter supplied to {@code function} on call - * @param arg8 parameter supplied to {@code function} on call - * @param arg9 parameter supplied to {@code function} on call - * @param arg10 parameter supplied to {@code function} on call - * @param arg11 parameter supplied to {@code function} on call - * @param arg12 parameter supplied to {@code function} on call - * @return a {@link PooledSupplier}, equivalent to lambda: - * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, - * arg11) } - */ - static <A, B, C, D, E, F, G, H, I, J, K, L, R> PooledSupplier<R> obtainSupplier( - DodecFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, - ? super G, ? super H, ? super I, ? super J, ? super K, ? extends L, - ? extends R> function, - A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, - K arg11, L arg12) { - return acquire(PooledLambdaImpl.sPool, - function, 11, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, - arg9, arg10, arg11, arg12); - } - - /** * Factory of {@link Message}s that contain an * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its * {@link Message#getCallback internal callback}. diff --git a/tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java b/tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java index 388548691b77..2001c04bd645 100644 --- a/tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java +++ b/tests/benchmarks/internal/src/com/android/internal/LambdaPerfTest.java @@ -1,454 +1,458 @@ -/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import android.app.Activity;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Message;
-import android.os.ParcelFileDescriptor;
-import android.os.Process;
-import android.os.SystemClock;
-import android.util.Log;
-
-import androidx.test.filters.LargeTest;
-
-import com.android.internal.util.function.pooled.PooledConsumer;
-import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.internal.util.function.pooled.PooledPredicate;
-
-import org.junit.Assume;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runners.model.Statement;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/** Compares the performance of regular lambda and pooled lambda. */
-@LargeTest
-public class LambdaPerfTest {
- private static final boolean DEBUG = false;
- private static final String TAG = LambdaPerfTest.class.getSimpleName();
-
- private static final String LAMBDA_FORM_REGULAR = "regular";
- private static final String LAMBDA_FORM_POOLED = "pooled";
-
- private static final int WARMUP_ITERATIONS = 1000;
- private static final int TEST_ITERATIONS = 3000000;
- private static final int TASK_COUNT = 10;
- private static final long DELAY_AFTER_BENCH_MS = 1000;
-
- private String mMethodName;
-
- private final Bundle mTestResults = new Bundle();
- private final ArrayList<Task> mTasks = new ArrayList<>();
-
- // The member fields are used to ensure lambda capturing. They don't have the actual meaning.
- private final Task mTask = new Task();
- private final Rect mBounds = new Rect();
- private int mTaskId;
- private long mTime;
- private boolean mTop;
-
- @Rule
- public final TestRule mRule = (base, description) -> new Statement() {
- @Override
- public void evaluate() throws Throwable {
- mMethodName = description.getMethodName();
- mTasks.clear();
- for (int i = 0; i < TASK_COUNT; i++) {
- final Task t = new Task();
- mTasks.add(t);
- }
- base.evaluate();
-
- getInstrumentation().sendStatus(Activity.RESULT_OK, mTestResults);
- }
- };
-
- @Test
- public void test1ParamConsumer() {
- evaluate(LAMBDA_FORM_REGULAR, () -> forAllTask(t -> t.doSomething(mTask)));
- evaluate(LAMBDA_FORM_POOLED, () -> {
- final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething,
- PooledLambda.__(Task.class), mTask);
- forAllTask(c);
- c.recycle();
- });
- }
-
- @Test
- public void test2PrimitiveParamsConsumer() {
- // Not in Integer#IntegerCache (-128~127) for autoboxing, that will create new object.
- mTaskId = 12345;
- mTime = 54321;
-
- evaluate(LAMBDA_FORM_REGULAR, () -> forAllTask(t -> t.doSomething(mTaskId, mTime)));
- evaluate(LAMBDA_FORM_POOLED, () -> {
- final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething,
- PooledLambda.__(Task.class), mTaskId, mTime);
- forAllTask(c);
- c.recycle();
- });
- }
-
- @Test
- public void test3ParamsPredicate() {
- mTop = true;
- // In Integer#IntegerCache.
- mTaskId = 10;
-
- evaluate(LAMBDA_FORM_REGULAR, () -> handleTask(t -> t.doSomething(mBounds, mTop, mTaskId)));
- evaluate(LAMBDA_FORM_POOLED, () -> {
- final PooledPredicate c = PooledLambda.obtainPredicate(Task::doSomething,
- PooledLambda.__(Task.class), mBounds, mTop, mTaskId);
- handleTask(c);
- c.recycle();
- });
- }
-
- @Test
- public void testMessage() {
- evaluate(LAMBDA_FORM_REGULAR, () -> {
- final Message m = Message.obtain().setCallback(() -> mTask.doSomething(mTaskId, mTime));
- m.getCallback().run();
- m.recycle();
- });
- evaluate(LAMBDA_FORM_POOLED, () -> {
- final Message m = PooledLambda.obtainMessage(Task::doSomething, mTask, mTaskId, mTime);
- m.getCallback().run();
- m.recycle();
- });
- }
-
- @Test
- public void testRunnable() {
- evaluate(LAMBDA_FORM_REGULAR, () -> {
- final Runnable r = mTask::doSomething;
- r.run();
- });
- evaluate(LAMBDA_FORM_POOLED, () -> {
- final Runnable r = PooledLambda.obtainRunnable(Task::doSomething, mTask).recycleOnUse();
- r.run();
- });
- }
-
- @Test
- public void testMultiThread() {
- final int numThread = 3;
-
- final Runnable regularAction = () -> forAllTask(t -> t.doSomething(mTask));
- final Runnable[] regularActions = new Runnable[numThread];
- Arrays.fill(regularActions, regularAction);
- evaluateMultiThread(LAMBDA_FORM_REGULAR, regularActions);
-
- final Runnable pooledAction = () -> {
- final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething,
- PooledLambda.__(Task.class), mTask);
- forAllTask(c);
- c.recycle();
- };
- final Runnable[] pooledActions = new Runnable[numThread];
- Arrays.fill(pooledActions, pooledAction);
- evaluateMultiThread(LAMBDA_FORM_POOLED, pooledActions);
- }
-
- private void forAllTask(Consumer<Task> callback) {
- for (int i = mTasks.size() - 1; i >= 0; i--) {
- callback.accept(mTasks.get(i));
- }
- }
-
- private void handleTask(Predicate<Task> callback) {
- for (int i = mTasks.size() - 1; i >= 0; i--) {
- final Task task = mTasks.get(i);
- if (callback.test(task)) {
- return;
- }
- }
- }
-
- private void evaluate(String title, Runnable action) {
- for (int i = 0; i < WARMUP_ITERATIONS; i++) {
- action.run();
- }
- performGc();
-
- final GcStatus startGcStatus = getGcStatus();
- final long startTime = SystemClock.elapsedRealtime();
- for (int i = 0; i < TEST_ITERATIONS; i++) {
- action.run();
- }
- evaluateResult(title, startGcStatus, startTime);
- }
-
- private void evaluateMultiThread(String title, Runnable[] actions) {
- performGc();
-
- final CountDownLatch latch = new CountDownLatch(actions.length);
- final GcStatus startGcStatus = getGcStatus();
- final long startTime = SystemClock.elapsedRealtime();
- for (Runnable action : actions) {
- new Thread() {
- @Override
- public void run() {
- for (int i = 0; i < TEST_ITERATIONS; i++) {
- action.run();
- }
- latch.countDown();
- };
- }.start();
- }
- try {
- latch.await();
- } catch (InterruptedException ignored) {
- }
- evaluateResult(title, startGcStatus, startTime);
- }
-
- private void evaluateResult(String title, GcStatus startStatus, long startTime) {
- final float elapsed = SystemClock.elapsedRealtime() - startTime;
- // Sleep a while to see if GC may happen.
- SystemClock.sleep(DELAY_AFTER_BENCH_MS);
- final GcStatus endStatus = getGcStatus();
- final GcInfo info = startStatus.calculateGcTime(endStatus, title, mTestResults);
- Log.i(TAG, mMethodName + "_" + title + " execution time: "
- + elapsed + "ms (avg=" + String.format("%.5f", elapsed / TEST_ITERATIONS) + "ms)"
- + " GC time: " + String.format("%.3f", info.mTotalGcTime) + "ms"
- + " GC paused time: " + String.format("%.3f", info.mTotalGcPausedTime) + "ms");
- }
-
- /** Cleans the test environment. */
- private static void performGc() {
- System.gc();
- System.runFinalization();
- System.gc();
- }
-
- private static GcStatus getGcStatus() {
- if (DEBUG) {
- Log.i(TAG, "===== Read GC dump =====");
- }
- final GcStatus status = new GcStatus();
- final List<String> vmDump = getVmDump();
- Assume.assumeFalse("VM dump is empty", vmDump.isEmpty());
- for (String line : vmDump) {
- status.visit(line);
- if (line.startsWith("DALVIK THREADS")) {
- break;
- }
- }
- return status;
- }
-
- private static List<String> getVmDump() {
- final int myPid = Process.myPid();
- // Another approach Debug#dumpJavaBacktraceToFileTimeout requires setenforce 0.
- Process.sendSignal(myPid, Process.SIGNAL_QUIT);
- // Give a chance to handle the signal.
- SystemClock.sleep(100);
-
- String dump = null;
- final String pattern = myPid + " written to: ";
- final List<String> logs = shell("logcat -v brief -d tombstoned:I *:S");
- for (int i = logs.size() - 1; i >= 0; i--) {
- final String log = logs.get(i);
- // Log pattern: Traces for pid 9717 written to: /data/anr/trace_07
- final int pos = log.indexOf(pattern);
- if (pos > 0) {
- dump = log.substring(pattern.length() + pos);
- break;
- }
- }
-
- Assume.assumeNotNull("Unable to find VM dump", dump);
- // It requires system or root uid to read the trace.
- return shell("cat " + dump);
- }
-
- private static List<String> shell(String command) {
- final ParcelFileDescriptor.AutoCloseInputStream stream =
- new ParcelFileDescriptor.AutoCloseInputStream(
- getInstrumentation().getUiAutomation().executeShellCommand(command));
- final ArrayList<String> lines = new ArrayList<>();
- try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
- String line;
- while ((line = br.readLine()) != null) {
- lines.add(line);
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return lines;
- }
-
- /** An empty class which provides some methods with different type arguments. */
- static class Task {
- void doSomething() {
- }
-
- void doSomething(Task t) {
- }
-
- void doSomething(int taskId, long time) {
- }
-
- boolean doSomething(Rect bounds, boolean top, int taskId) {
- return false;
- }
- }
-
- static class ValPattern {
- static final int TYPE_COUNT = 0;
- static final int TYPE_TIME = 1;
- static final String PATTERN_COUNT = "(\\d+)";
- static final String PATTERN_TIME = "(\\d+\\.?\\d+)(\\w+)";
- final String mRawPattern;
- final Pattern mPattern;
- final int mType;
-
- int mIntValue;
- float mFloatValue;
-
- ValPattern(String p, int type) {
- mRawPattern = p;
- mPattern = Pattern.compile(
- p + (type == TYPE_TIME ? PATTERN_TIME : PATTERN_COUNT) + ".*");
- mType = type;
- }
-
- boolean visit(String line) {
- final Matcher matcher = mPattern.matcher(line);
- if (!matcher.matches()) {
- return false;
- }
- final String value = matcher.group(1);
- if (value == null) {
- return false;
- }
- if (mType == TYPE_COUNT) {
- mIntValue = Integer.parseInt(value);
- return true;
- }
- final float time = Float.parseFloat(value);
- final String unit = matcher.group(2);
- if (unit == null) {
- return false;
- }
- // Refer to art/libartbase/base/time_utils.cc
- switch (unit) {
- case "s":
- mFloatValue = time * 1000;
- break;
- case "ms":
- mFloatValue = time;
- break;
- case "us":
- mFloatValue = time / 1000;
- break;
- case "ns":
- mFloatValue = time / 1000 / 1000;
- break;
- default:
- throw new IllegalArgumentException();
- }
-
- return true;
- }
-
- @Override
- public String toString() {
- return mRawPattern + (mType == TYPE_TIME ? (mFloatValue + "ms") : mIntValue);
- }
- }
-
- /** Parses the dump pattern of Heap::DumpGcPerformanceInfo. */
- private static class GcStatus {
- private static final int TOTAL_GC_TIME_INDEX = 1;
- private static final int TOTAL_GC_PAUSED_TIME_INDEX = 5;
-
- // Refer to art/runtime/gc/heap.cc
- final ValPattern[] mPatterns = {
- new ValPattern("Total GC count: ", ValPattern.TYPE_COUNT),
- new ValPattern("Total GC time: ", ValPattern.TYPE_TIME),
- new ValPattern("Total time waiting for GC to complete: ", ValPattern.TYPE_TIME),
- new ValPattern("Total blocking GC count: ", ValPattern.TYPE_COUNT),
- new ValPattern("Total blocking GC time: ", ValPattern.TYPE_TIME),
- new ValPattern("Total mutator paused time: ", ValPattern.TYPE_TIME),
- new ValPattern("Total number of allocations ", ValPattern.TYPE_COUNT),
- new ValPattern("concurrent copying paused: Sum: ", ValPattern.TYPE_TIME),
- new ValPattern("concurrent copying total time: ", ValPattern.TYPE_TIME),
- new ValPattern("concurrent copying freed: ", ValPattern.TYPE_COUNT),
- new ValPattern("Peak regions allocated ", ValPattern.TYPE_COUNT),
- };
-
- void visit(String dumpLine) {
- for (ValPattern p : mPatterns) {
- if (p.visit(dumpLine)) {
- if (DEBUG) {
- Log.i(TAG, " " + p);
- }
- }
- }
- }
-
- GcInfo calculateGcTime(GcStatus newStatus, String title, Bundle result) {
- Log.i(TAG, "===== GC status of " + title + " =====");
- final GcInfo info = new GcInfo();
- for (int i = 0; i < mPatterns.length; i++) {
- final ValPattern p = mPatterns[i];
- if (p.mType == ValPattern.TYPE_COUNT) {
- final int diff = newStatus.mPatterns[i].mIntValue - p.mIntValue;
- Log.i(TAG, " " + p.mRawPattern + diff);
- if (diff > 0) {
- result.putInt("[" + title + "] " + p.mRawPattern, diff);
- }
- continue;
- }
- final float diff = newStatus.mPatterns[i].mFloatValue - p.mFloatValue;
- Log.i(TAG, " " + p.mRawPattern + diff + "ms");
- if (diff > 0) {
- result.putFloat("[" + title + "] " + p.mRawPattern + "(ms)", diff);
- }
- if (i == TOTAL_GC_TIME_INDEX) {
- info.mTotalGcTime = diff;
- } else if (i == TOTAL_GC_PAUSED_TIME_INDEX) {
- info.mTotalGcPausedTime = diff;
- }
- }
- return info;
- }
- }
-
- private static class GcInfo {
- float mTotalGcTime;
- float mTotalGcPausedTime;
- }
-}
+/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import android.app.Activity; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.Message; +import android.os.ParcelFileDescriptor; +import android.os.Process; +import android.os.SystemClock; +import android.util.Log; + +import androidx.test.filters.LargeTest; + +import com.android.internal.util.function.pooled.PooledConsumer; +import com.android.internal.util.function.pooled.PooledLambda; +import com.android.internal.util.function.pooled.PooledPredicate; + +import org.junit.Assume; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runners.model.Statement; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** Compares the performance of regular lambda and pooled lambda. */ +@LargeTest +public class LambdaPerfTest { + private static final boolean DEBUG = false; + private static final String TAG = LambdaPerfTest.class.getSimpleName(); + + private static final String LAMBDA_FORM_REGULAR = "regular"; + private static final String LAMBDA_FORM_POOLED = "pooled"; + + private static final int WARMUP_ITERATIONS = 1000; + private static final int TEST_ITERATIONS = 3000000; + private static final int TASK_COUNT = 10; + private static final long DELAY_AFTER_BENCH_MS = 1000; + + private String mMethodName; + + private final Bundle mTestResults = new Bundle(); + private final ArrayList<Task> mTasks = new ArrayList<>(); + + // The member fields are used to ensure lambda capturing. They don't have the actual meaning. + private final Task mTask = new Task(); + private final Rect mBounds = new Rect(); + private int mTaskId; + private long mTime; + private boolean mTop; + + @Rule + public final TestRule mRule = (base, description) -> new Statement() { + @Override + public void evaluate() throws Throwable { + mMethodName = description.getMethodName(); + mTasks.clear(); + for (int i = 0; i < TASK_COUNT; i++) { + final Task t = new Task(); + mTasks.add(t); + } + base.evaluate(); + + getInstrumentation().sendStatus(Activity.RESULT_OK, mTestResults); + } + }; + + @Test + public void test1ParamConsumer() { + evaluate(LAMBDA_FORM_REGULAR, () -> forAllTask(t -> t.doSomething(mTask))); + evaluate(LAMBDA_FORM_POOLED, () -> { + final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, + PooledLambda.__(Task.class), mTask); + forAllTask(c); + c.recycle(); + }); + } + + @Test + public void test2PrimitiveParamsConsumer() { + // Not in Integer#IntegerCache (-128~127) for autoboxing, that may create new object. + mTaskId = 12345; + mTime = 54321; + + evaluate(LAMBDA_FORM_REGULAR, () -> forAllTask(t -> t.doSomething(mTaskId, mTime))); + evaluate(LAMBDA_FORM_POOLED, () -> { + final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, + PooledLambda.__(Task.class), mTaskId, mTime); + forAllTask(c); + c.recycle(); + }); + } + + @Test + public void test3ParamsPredicate() { + mTop = true; + // In Integer#IntegerCache. + mTaskId = 10; + + evaluate(LAMBDA_FORM_REGULAR, () -> handleTask(t -> t.doSomething(mBounds, mTop, mTaskId))); + evaluate(LAMBDA_FORM_POOLED, () -> { + final PooledPredicate c = PooledLambda.obtainPredicate(Task::doSomething, + PooledLambda.__(Task.class), mBounds, mTop, mTaskId); + handleTask(c); + c.recycle(); + }); + } + + @Test + public void testMessage() { + evaluate(LAMBDA_FORM_REGULAR, () -> { + final Message m = Message.obtain().setCallback(() -> mTask.doSomething(mTaskId, mTime)); + m.getCallback().run(); + m.recycle(); + }); + evaluate(LAMBDA_FORM_POOLED, () -> { + final Message m = PooledLambda.obtainMessage(Task::doSomething, mTask, mTaskId, mTime); + m.getCallback().run(); + m.recycle(); + }); + } + + @Test + public void testRunnable() { + evaluate(LAMBDA_FORM_REGULAR, () -> { + final Runnable r = mTask::doSomething; + r.run(); + }); + evaluate(LAMBDA_FORM_POOLED, () -> { + final Runnable r = PooledLambda.obtainRunnable(Task::doSomething, mTask).recycleOnUse(); + r.run(); + }); + } + + @Test + public void testMultiThread() { + final int numThread = 3; + + final Runnable regularAction = () -> forAllTask(t -> t.doSomething(mTask)); + final Runnable[] regularActions = new Runnable[numThread]; + Arrays.fill(regularActions, regularAction); + evaluateMultiThread(LAMBDA_FORM_REGULAR, regularActions); + + final Runnable pooledAction = () -> { + final PooledConsumer c = PooledLambda.obtainConsumer(Task::doSomething, + PooledLambda.__(Task.class), mTask); + forAllTask(c); + c.recycle(); + }; + final Runnable[] pooledActions = new Runnable[numThread]; + Arrays.fill(pooledActions, pooledAction); + evaluateMultiThread(LAMBDA_FORM_POOLED, pooledActions); + } + + private void forAllTask(Consumer<Task> callback) { + for (int i = mTasks.size() - 1; i >= 0; i--) { + callback.accept(mTasks.get(i)); + } + } + + private void handleTask(Predicate<Task> callback) { + for (int i = mTasks.size() - 1; i >= 0; i--) { + final Task task = mTasks.get(i); + if (callback.test(task)) { + return; + } + } + } + + private void evaluate(String title, Runnable action) { + for (int i = 0; i < WARMUP_ITERATIONS; i++) { + action.run(); + } + performGc(); + + final GcStatus startGcStatus = getGcStatus(); + final long startTime = SystemClock.elapsedRealtime(); + for (int i = 0; i < TEST_ITERATIONS; i++) { + action.run(); + } + evaluateResult(title, startGcStatus, startTime); + } + + private void evaluateMultiThread(String title, Runnable[] actions) { + performGc(); + + final CountDownLatch latch = new CountDownLatch(actions.length); + final GcStatus startGcStatus = getGcStatus(); + final long startTime = SystemClock.elapsedRealtime(); + for (Runnable action : actions) { + new Thread() { + @Override + public void run() { + for (int i = 0; i < TEST_ITERATIONS; i++) { + action.run(); + } + latch.countDown(); + }; + }.start(); + } + try { + latch.await(); + } catch (InterruptedException ignored) { + } + evaluateResult(title, startGcStatus, startTime); + } + + private void evaluateResult(String title, GcStatus startStatus, long startTime) { + final float elapsed = SystemClock.elapsedRealtime() - startTime; + // Sleep a while to see if GC may happen. + SystemClock.sleep(DELAY_AFTER_BENCH_MS); + final GcStatus endStatus = getGcStatus(); + final GcInfo info = startStatus.calculateGcTime(endStatus, title, mTestResults); + mTestResults.putFloat("[" + title + "-execution-time]", elapsed); + Log.i(TAG, mMethodName + "_" + title + " execution time: " + + elapsed + "ms (avg=" + String.format("%.5f", elapsed / TEST_ITERATIONS) + "ms)" + + " GC time: " + String.format("%.3f", info.mTotalGcTime) + "ms" + + " GC paused time: " + String.format("%.3f", info.mTotalGcPausedTime) + "ms"); + } + + /** Cleans the test environment. */ + private static void performGc() { + System.gc(); + System.runFinalization(); + System.gc(); + } + + private static GcStatus getGcStatus() { + if (DEBUG) { + Log.i(TAG, "===== Read GC dump ====="); + } + final GcStatus status = new GcStatus(); + final List<String> vmDump = getVmDump(); + Assume.assumeFalse("VM dump is empty", vmDump.isEmpty()); + for (String line : vmDump) { + status.visit(line); + if (line.startsWith("DALVIK THREADS")) { + break; + } + } + return status; + } + + private static List<String> getVmDump() { + final int myPid = Process.myPid(); + // Another approach Debug#dumpJavaBacktraceToFileTimeout requires setenforce 0. + Process.sendSignal(myPid, Process.SIGNAL_QUIT); + // Give a chance to handle the signal. + SystemClock.sleep(100); + + String dump = null; + final String pattern = myPid + " written to: "; + final List<String> logs = shell("logcat -v brief -d tombstoned:I *:S"); + for (int i = logs.size() - 1; i >= 0; i--) { + final String log = logs.get(i); + // Log pattern: Traces for pid 9717 written to: /data/anr/trace_07 + final int pos = log.indexOf(pattern); + if (pos > 0) { + dump = log.substring(pattern.length() + pos); + if (!dump.startsWith("/data/anr/")) { + dump = "/data/anr/" + dump; + } + break; + } + } + + Assume.assumeNotNull("Unable to find VM dump", dump); + // It requires system or root uid to read the trace. + return shell("cat " + dump); + } + + private static List<String> shell(String command) { + final ParcelFileDescriptor.AutoCloseInputStream stream = + new ParcelFileDescriptor.AutoCloseInputStream( + getInstrumentation().getUiAutomation().executeShellCommand(command)); + final ArrayList<String> lines = new ArrayList<>(); + try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) { + String line; + while ((line = br.readLine()) != null) { + lines.add(line); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return lines; + } + + /** An empty class which provides some methods with different type arguments. */ + static class Task { + void doSomething() { + } + + void doSomething(Task t) { + } + + void doSomething(int taskId, long time) { + } + + boolean doSomething(Rect bounds, boolean top, int taskId) { + return false; + } + } + + static class ValPattern { + static final int TYPE_COUNT = 0; + static final int TYPE_TIME = 1; + static final String PATTERN_COUNT = "(\\d+)"; + static final String PATTERN_TIME = "(\\d+\\.?\\d+)(\\w+)"; + final String mRawPattern; + final Pattern mPattern; + final int mType; + + int mIntValue; + float mFloatValue; + + ValPattern(String p, int type) { + mRawPattern = p; + mPattern = Pattern.compile( + p + (type == TYPE_TIME ? PATTERN_TIME : PATTERN_COUNT) + ".*"); + mType = type; + } + + boolean visit(String line) { + final Matcher matcher = mPattern.matcher(line); + if (!matcher.matches()) { + return false; + } + final String value = matcher.group(1); + if (value == null) { + return false; + } + if (mType == TYPE_COUNT) { + mIntValue = Integer.parseInt(value); + return true; + } + final float time = Float.parseFloat(value); + final String unit = matcher.group(2); + if (unit == null) { + return false; + } + // Refer to art/libartbase/base/time_utils.cc + switch (unit) { + case "s": + mFloatValue = time * 1000; + break; + case "ms": + mFloatValue = time; + break; + case "us": + mFloatValue = time / 1000; + break; + case "ns": + mFloatValue = time / 1000 / 1000; + break; + default: + throw new IllegalArgumentException(); + } + + return true; + } + + @Override + public String toString() { + return mRawPattern + (mType == TYPE_TIME ? (mFloatValue + "ms") : mIntValue); + } + } + + /** Parses the dump pattern of Heap::DumpGcPerformanceInfo. */ + private static class GcStatus { + private static final int TOTAL_GC_TIME_INDEX = 1; + private static final int TOTAL_GC_PAUSED_TIME_INDEX = 5; + + // Refer to art/runtime/gc/heap.cc + final ValPattern[] mPatterns = { + new ValPattern("Total GC count: ", ValPattern.TYPE_COUNT), + new ValPattern("Total GC time: ", ValPattern.TYPE_TIME), + new ValPattern("Total time waiting for GC to complete: ", ValPattern.TYPE_TIME), + new ValPattern("Total blocking GC count: ", ValPattern.TYPE_COUNT), + new ValPattern("Total blocking GC time: ", ValPattern.TYPE_TIME), + new ValPattern("Total mutator paused time: ", ValPattern.TYPE_TIME), + new ValPattern("Total number of allocations ", ValPattern.TYPE_COUNT), + new ValPattern("concurrent copying paused: Sum: ", ValPattern.TYPE_TIME), + new ValPattern("concurrent copying total time: ", ValPattern.TYPE_TIME), + new ValPattern("concurrent copying freed: ", ValPattern.TYPE_COUNT), + new ValPattern("Peak regions allocated ", ValPattern.TYPE_COUNT), + }; + + void visit(String dumpLine) { + for (ValPattern p : mPatterns) { + if (p.visit(dumpLine)) { + if (DEBUG) { + Log.i(TAG, " " + p); + } + } + } + } + + GcInfo calculateGcTime(GcStatus newStatus, String title, Bundle result) { + Log.i(TAG, "===== GC status of " + title + " ====="); + final GcInfo info = new GcInfo(); + for (int i = 0; i < mPatterns.length; i++) { + final ValPattern p = mPatterns[i]; + if (p.mType == ValPattern.TYPE_COUNT) { + final int diff = newStatus.mPatterns[i].mIntValue - p.mIntValue; + Log.i(TAG, " " + p.mRawPattern + diff); + if (diff > 0) { + result.putInt("[" + title + "] " + p.mRawPattern, diff); + } + continue; + } + final float diff = newStatus.mPatterns[i].mFloatValue - p.mFloatValue; + Log.i(TAG, " " + p.mRawPattern + diff + "ms"); + if (diff > 0) { + result.putFloat("[" + title + "] " + p.mRawPattern + "(ms)", diff); + } + if (i == TOTAL_GC_TIME_INDEX) { + info.mTotalGcTime = diff; + } else if (i == TOTAL_GC_PAUSED_TIME_INDEX) { + info.mTotalGcPausedTime = diff; + } + } + return info; + } + } + + private static class GcInfo { + float mTotalGcTime; + float mTotalGcPausedTime; + } +} |