summaryrefslogtreecommitdiff
path: root/common/testutils/devicetests/com/android/testutils/async/RateLimiter.java
diff options
context:
space:
mode:
Diffstat (limited to 'common/testutils/devicetests/com/android/testutils/async/RateLimiter.java')
-rw-r--r--common/testutils/devicetests/com/android/testutils/async/RateLimiter.java131
1 files changed, 0 insertions, 131 deletions
diff --git a/common/testutils/devicetests/com/android/testutils/async/RateLimiter.java b/common/testutils/devicetests/com/android/testutils/async/RateLimiter.java
deleted file mode 100644
index d5cca0a4..00000000
--- a/common/testutils/devicetests/com/android/testutils/async/RateLimiter.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2023 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.testutils.async;
-
-import com.android.net.module.util.async.OsAccess;
-
-import java.util.Arrays;
-
-/**
- * Limits the number of bytes processed to the given maximum of bytes per second.
- *
- * The limiter tracks the total for the past second, along with sums for each 10ms
- * in the past second, allowing the total to be adjusted as the time passes.
- */
-public final class RateLimiter {
- private static final int PERIOD_DURATION_MS = 1000;
- private static final int BUCKET_COUNT = 100;
-
- public static final int BUCKET_DURATION_MS = PERIOD_DURATION_MS / BUCKET_COUNT;
-
- private final OsAccess mOsAccess;
- private final int[] mStatBuckets = new int[BUCKET_COUNT];
- private int mMaxPerPeriodBytes;
- private int mMaxPerBucketBytes;
- private int mRecordedPeriodBytes;
- private long mLastLimitTimestamp;
- private int mLastRequestReduction;
-
- public RateLimiter(OsAccess osAccess, int bytesPerSecond) {
- mOsAccess = osAccess;
- setBytesPerSecond(bytesPerSecond);
- clear();
- }
-
- public int getBytesPerSecond() {
- return mMaxPerPeriodBytes;
- }
-
- public void setBytesPerSecond(int bytesPerSecond) {
- mMaxPerPeriodBytes = bytesPerSecond;
- mMaxPerBucketBytes = Math.max(1, (mMaxPerPeriodBytes / BUCKET_COUNT) * 2);
- }
-
- public void clear() {
- mLastLimitTimestamp = mOsAccess.monotonicTimeMillis();
- mRecordedPeriodBytes = 0;
- Arrays.fill(mStatBuckets, 0);
- }
-
- public static int limit(RateLimiter limiter1, RateLimiter limiter2, int requestedBytes) {
- final long now = limiter1.mOsAccess.monotonicTimeMillis();
- final int allowedCount = Math.min(limiter1.calculateLimit(now, requestedBytes),
- limiter2.calculateLimit(now, requestedBytes));
- limiter1.recordBytes(now, requestedBytes, allowedCount);
- limiter2.recordBytes(now, requestedBytes, allowedCount);
- return allowedCount;
- }
-
- public int limit(int requestedBytes) {
- final long now = mOsAccess.monotonicTimeMillis();
- final int allowedCount = calculateLimit(now, requestedBytes);
- recordBytes(now, requestedBytes, allowedCount);
- return allowedCount;
- }
-
- public int getLastRequestReduction() {
- return mLastRequestReduction;
- }
-
- public boolean acceptAllOrNone(int requestedBytes) {
- final long now = mOsAccess.monotonicTimeMillis();
- final int allowedCount = calculateLimit(now, requestedBytes);
- if (allowedCount < requestedBytes) {
- return false;
- }
- recordBytes(now, requestedBytes, allowedCount);
- return true;
- }
-
- private int calculateLimit(long now, int requestedBytes) {
- // First remove all stale bucket data and adjust the total.
- final long currentBucketAbsIdx = now / BUCKET_DURATION_MS;
- final long staleCutoffIdx = currentBucketAbsIdx - BUCKET_COUNT;
- for (long i = mLastLimitTimestamp / BUCKET_DURATION_MS; i < staleCutoffIdx; i++) {
- final int idx = (int) (i % BUCKET_COUNT);
- mRecordedPeriodBytes -= mStatBuckets[idx];
- mStatBuckets[idx] = 0;
- }
-
- final int bucketIdx = (int) (currentBucketAbsIdx % BUCKET_COUNT);
- final int maxAllowed = Math.min(mMaxPerPeriodBytes - mRecordedPeriodBytes,
- Math.min(mMaxPerBucketBytes - mStatBuckets[bucketIdx], requestedBytes));
- return Math.max(0, maxAllowed);
- }
-
- private void recordBytes(long now, int requestedBytes, int actualBytes) {
- mStatBuckets[(int) ((now / BUCKET_DURATION_MS) % BUCKET_COUNT)] += actualBytes;
- mRecordedPeriodBytes += actualBytes;
- mLastRequestReduction = requestedBytes - actualBytes;
- mLastLimitTimestamp = now;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("{max=");
- sb.append(mMaxPerPeriodBytes);
- sb.append(",max_bucket=");
- sb.append(mMaxPerBucketBytes);
- sb.append(",total=");
- sb.append(mRecordedPeriodBytes);
- sb.append(",last_red=");
- sb.append(mLastRequestReduction);
- sb.append('}');
- return sb.toString();
- }
-}