blob: 8d2d04471f8e17b2f179d481cc07fce5b80e6830 [file] [log] [blame]
/*
* Copyright (C) 2021 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 android.os;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.LongArrayMultiStateCounter;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class LongArrayMultiStateCounterPerfTest {
@Rule
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
/**
* A complete line-for-line reimplementation of
* {@link com.android.internal.os.LongArrayMultiStateCounter}, only in Java instead of
* native.
*/
private static class TestLongArrayMultiStateCounter {
private final int mStateCount;
private final int mArrayLength;
private int mCurrentState;
private long mLastStateChangeTimestampMs = -1;
private long mLastUpdateTimestampMs = -1;
private static class State {
private long mTimeInStateSinceUpdate;
private long[] mCounter;
}
private final State[] mStates;
private final long[] mLastTimeInFreq;
private final long[] mDelta;
TestLongArrayMultiStateCounter(int stateCount, int arrayLength) {
mStateCount = stateCount;
mArrayLength = arrayLength;
mStates = new State[stateCount];
for (int i = 0; i < mStateCount; i++) {
mStates[i] = new State();
mStates[i].mCounter = new long[mArrayLength];
}
mLastTimeInFreq = new long[mArrayLength];
mDelta = new long[mArrayLength];
}
public void setState(int state, long timestampMs) {
if (mLastStateChangeTimestampMs > 0) {
if (timestampMs >= mLastStateChangeTimestampMs) {
mStates[mCurrentState].mTimeInStateSinceUpdate +=
timestampMs - mLastStateChangeTimestampMs;
} else {
for (int i = 0; i < mStateCount; i++) {
mStates[i].mTimeInStateSinceUpdate = 0;
}
}
}
mCurrentState = state;
mLastStateChangeTimestampMs = timestampMs;
}
public void updateValue(long[] timeInFreq, long timestampMs) {
setState(mCurrentState, timestampMs);
if (mLastUpdateTimestampMs >= 0) {
if (timestampMs > mLastUpdateTimestampMs) {
if (delta(mLastTimeInFreq, timeInFreq, mDelta)) {
long timeSinceUpdate = timestampMs - mLastUpdateTimestampMs;
for (int i = 0; i < mStateCount; i++) {
long timeInState = mStates[i].mTimeInStateSinceUpdate;
if (timeInState > 0) {
add(mStates[i].mCounter, mDelta, timeInState, timeSinceUpdate);
mStates[i].mTimeInStateSinceUpdate = 0;
}
}
} else {
throw new RuntimeException();
}
} else if (timestampMs < mLastUpdateTimestampMs) {
throw new RuntimeException();
}
}
System.arraycopy(timeInFreq, 0, mLastTimeInFreq, 0, mArrayLength);
mLastUpdateTimestampMs = timestampMs;
}
private boolean delta(long[] timeInFreq1, long[] timeInFreq2, long[] delta) {
if (delta.length != mArrayLength) {
throw new RuntimeException();
}
boolean is_delta_valid = true;
for (int i = 0; i < mStateCount; i++) {
if (timeInFreq2[i] >= timeInFreq1[i]) {
delta[i] = timeInFreq2[i] - timeInFreq1[i];
} else {
delta[i] = 0;
is_delta_valid = false;
}
}
return is_delta_valid;
}
private void add(long[] counter, long[] delta, long numerator, long denominator) {
if (numerator != denominator) {
for (int i = 0; i < mArrayLength; i++) {
counter[i] += delta[i] * numerator / denominator;
}
} else {
for (int i = 0; i < mArrayLength; i++) {
counter[i] += delta[i];
}
}
}
}
@Test
public void javaImplementation() {
TestLongArrayMultiStateCounter counter =
new TestLongArrayMultiStateCounter(2, 4);
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
long time = 1000;
long[] timeInFreq = {100, 200, 300, 400};
while (state.keepRunning()) {
counter.setState(1, time);
counter.setState(0, time + 1000);
counter.updateValue(timeInFreq, time + 2000);
time += 10000;
}
}
@Test
public void nativeImplementation() {
LongArrayMultiStateCounter counter = new LongArrayMultiStateCounter(2, 4);
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
long time = 1000;
LongArrayMultiStateCounter.LongArrayContainer timeInFreq =
new LongArrayMultiStateCounter.LongArrayContainer(4);
timeInFreq.setValues(new long[]{100, 200, 300, 400});
while (state.keepRunning()) {
counter.setState(1, time);
counter.setState(0, time + 1000);
counter.updateValues(timeInFreq, time + 2000);
time += 10000;
}
}
}