Merge "Remove unused pooled lambda methods"
This commit is contained in:
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -193,40 +181,6 @@ public interface PooledLambda {
|
||||
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> 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
|
||||
@@ -278,42 +232,6 @@ public interface PooledLambda {
|
||||
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> 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
|
||||
*
|
||||
@@ -410,24 +328,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
*
|
||||
@@ -464,24 +364,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
@@ -535,25 +417,6 @@ public interface PooledLambda {
|
||||
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
|
||||
* @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
|
||||
*
|
||||
@@ -573,25 +436,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
*
|
||||
@@ -611,25 +455,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
*
|
||||
@@ -649,25 +474,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
@@ -723,26 +529,6 @@ public interface PooledLambda {
|
||||
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
|
||||
* @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
|
||||
*
|
||||
@@ -763,26 +549,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
*
|
||||
@@ -803,26 +569,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
*
|
||||
@@ -843,26 +589,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
*
|
||||
@@ -883,26 +609,6 @@ public interface PooledLambda {
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
@@ -960,27 +666,6 @@ public interface PooledLambda {
|
||||
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
|
||||
* @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
|
||||
@@ -1041,28 +726,6 @@ public interface PooledLambda {
|
||||
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
|
||||
* @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
|
||||
@@ -1125,30 +788,6 @@ public interface PooledLambda {
|
||||
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
|
||||
* @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
|
||||
@@ -1214,31 +853,6 @@ public interface PooledLambda {
|
||||
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
|
||||
* @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
|
||||
@@ -1307,32 +921,6 @@ public interface PooledLambda {
|
||||
arg9, 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
|
||||
* @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
|
||||
@@ -1403,33 +991,6 @@ public interface PooledLambda {
|
||||
arg9, arg10, 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
|
||||
* @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
|
||||
@@ -1503,36 +1064,6 @@ public interface PooledLambda {
|
||||
arg9, arg10, arg11, 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
|
||||
* @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
|
||||
@@ -1610,38 +1141,6 @@ public interface PooledLambda {
|
||||
arg9, arg10, arg11, arg12);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user