Merge "Adjust concurrency limits based on device."

This commit is contained in:
TreeHugger Robot
2023-01-11 19:21:42 +00:00
committed by Android (Google) Code Review
5 changed files with 644 additions and 453 deletions

View File

@@ -17,6 +17,7 @@
package com.android.server.job;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.util.DataUnit.GIGABYTES;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
@@ -58,6 +59,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.StatLogger;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
@@ -85,11 +87,33 @@ class JobConcurrencyManager {
private static final boolean DEBUG = JobSchedulerService.DEBUG;
/** The maximum number of concurrent jobs we'll aim to run at one time. */
public static final int STANDARD_CONCURRENCY_LIMIT = 16;
@VisibleForTesting
static final int MAX_CONCURRENCY_LIMIT = 64;
/** The maximum number of objects we should retain in memory when not in use. */
private static final int MAX_RETAINED_OBJECTS = (int) (1.5 * STANDARD_CONCURRENCY_LIMIT);
private static final int MAX_RETAINED_OBJECTS = (int) (1.5 * MAX_CONCURRENCY_LIMIT);
static final String CONFIG_KEY_PREFIX_CONCURRENCY = "concurrency_";
private static final String KEY_CONCURRENCY_LIMIT = CONFIG_KEY_PREFIX_CONCURRENCY + "limit";
@VisibleForTesting
static final int DEFAULT_CONCURRENCY_LIMIT;
static {
if (ActivityManager.isLowRamDeviceStatic()) {
DEFAULT_CONCURRENCY_LIMIT = 8;
} else {
final long ramBytes = new MemInfoReader().getTotalSize();
if (ramBytes <= GIGABYTES.toBytes(6)) {
DEFAULT_CONCURRENCY_LIMIT = 16;
} else if (ramBytes <= GIGABYTES.toBytes(8)) {
DEFAULT_CONCURRENCY_LIMIT = 20;
} else if (ramBytes <= GIGABYTES.toBytes(12)) {
DEFAULT_CONCURRENCY_LIMIT = 32;
} else {
DEFAULT_CONCURRENCY_LIMIT = 40;
}
}
}
private static final String KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS =
CONFIG_KEY_PREFIX_CONCURRENCY + "screen_off_adjustment_delay_ms";
private static final long DEFAULT_SCREEN_OFF_ADJUSTMENT_DELAY_MS = 30_000;
@@ -100,7 +124,7 @@ class JobConcurrencyManager {
@VisibleForTesting
static final String KEY_PKG_CONCURRENCY_LIMIT_REGULAR =
CONFIG_KEY_PREFIX_CONCURRENCY + "pkg_concurrency_limit_regular";
private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = STANDARD_CONCURRENCY_LIMIT / 2;
private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = DEFAULT_CONCURRENCY_LIMIT / 2;
@VisibleForTesting
static final String KEY_ENABLE_MAX_WAIT_TIME_BYPASS =
CONFIG_KEY_PREFIX_CONCURRENCY + "enable_max_wait_time_bypass";
@@ -209,84 +233,100 @@ class JobConcurrencyManager {
private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_ON =
new WorkConfigLimitsPerMemoryTrimLevel(
new WorkTypeConfig("screen_on_normal", 11,
new WorkTypeConfig("screen_on_normal", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 3 / 4,
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
List.of(Pair.create(WORK_TYPE_TOP, .4f),
Pair.create(WORK_TYPE_FGS, .2f),
Pair.create(WORK_TYPE_EJ, .2f), Pair.create(WORK_TYPE_BG, .1f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 6),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
Pair.create(WORK_TYPE_BGUSER, 3))
List.of(Pair.create(WORK_TYPE_BG, .5f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .25f),
Pair.create(WORK_TYPE_BGUSER, .2f))
),
new WorkTypeConfig("screen_on_moderate", 9,
new WorkTypeConfig("screen_on_moderate", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT / 2,
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
List.of(Pair.create(WORK_TYPE_TOP, .4f),
Pair.create(WORK_TYPE_FGS, .1f),
Pair.create(WORK_TYPE_EJ, .1f), Pair.create(WORK_TYPE_BG, .1f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 4),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
Pair.create(WORK_TYPE_BGUSER, 1))
List.of(Pair.create(WORK_TYPE_BG, .4f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
Pair.create(WORK_TYPE_BGUSER, .1f))
),
new WorkTypeConfig("screen_on_low", 6,
new WorkTypeConfig("screen_on_low", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
Pair.create(WORK_TYPE_EJ, 1)),
List.of(Pair.create(WORK_TYPE_TOP, 2.0f / 3),
Pair.create(WORK_TYPE_FGS, .1f),
Pair.create(WORK_TYPE_EJ, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 2),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
Pair.create(WORK_TYPE_BGUSER, 1))
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1.0f / 6),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6))
),
new WorkTypeConfig("screen_on_critical", 6,
new WorkTypeConfig("screen_on_critical", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
Pair.create(WORK_TYPE_EJ, 1)),
List.of(Pair.create(WORK_TYPE_TOP, 2.0f / 3),
Pair.create(WORK_TYPE_FGS, .1f),
Pair.create(WORK_TYPE_EJ, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 1),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
Pair.create(WORK_TYPE_BGUSER, 1))
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 6),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1.0f / 6),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6))
)
);
private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_OFF =
new WorkConfigLimitsPerMemoryTrimLevel(
new WorkTypeConfig("screen_off_normal", 16,
new WorkTypeConfig("screen_off_normal", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT,
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 2),
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
List.of(Pair.create(WORK_TYPE_TOP, .3f),
Pair.create(WORK_TYPE_FGS, .2f),
Pair.create(WORK_TYPE_EJ, .3f), Pair.create(WORK_TYPE_BG, .2f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 10),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
Pair.create(WORK_TYPE_BGUSER, 3))
List.of(Pair.create(WORK_TYPE_BG, .6f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .2f),
Pair.create(WORK_TYPE_BGUSER, .2f))
),
new WorkTypeConfig("screen_off_moderate", 14,
new WorkTypeConfig("screen_off_moderate", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 9 / 10,
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 2),
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
List.of(Pair.create(WORK_TYPE_TOP, .3f),
Pair.create(WORK_TYPE_FGS, .2f),
Pair.create(WORK_TYPE_EJ, .3f), Pair.create(WORK_TYPE_BG, .2f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 7),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
Pair.create(WORK_TYPE_BGUSER, 1))
List.of(Pair.create(WORK_TYPE_BG, .5f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
Pair.create(WORK_TYPE_BGUSER, .1f))
),
new WorkTypeConfig("screen_off_low", 9,
new WorkTypeConfig("screen_off_low", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 6 / 10,
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1)),
List.of(Pair.create(WORK_TYPE_TOP, .4f),
Pair.create(WORK_TYPE_FGS, .1f),
Pair.create(WORK_TYPE_EJ, .2f), Pair.create(WORK_TYPE_BG, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 3),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
Pair.create(WORK_TYPE_BGUSER, 1))
List.of(Pair.create(WORK_TYPE_BG, .25f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
Pair.create(WORK_TYPE_BGUSER, .1f))
),
new WorkTypeConfig("screen_off_critical", 6,
new WorkTypeConfig("screen_off_critical", DEFAULT_CONCURRENCY_LIMIT,
/* defaultMaxTotal */ DEFAULT_CONCURRENCY_LIMIT * 4 / 10,
// defaultMin
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
Pair.create(WORK_TYPE_EJ, 1)),
List.of(Pair.create(WORK_TYPE_TOP, .5f),
Pair.create(WORK_TYPE_FGS, .1f),
Pair.create(WORK_TYPE_EJ, .1f)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 1),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
Pair.create(WORK_TYPE_BGUSER, 1))
List.of(Pair.create(WORK_TYPE_BG, .1f),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, .1f),
Pair.create(WORK_TYPE_BGUSER, .1f))
)
);
@@ -357,6 +397,12 @@ class JobConcurrencyManager {
/** Wait for this long after screen off before adjusting the job concurrency. */
private long mScreenOffAdjustmentDelayMs = DEFAULT_SCREEN_OFF_ADJUSTMENT_DELAY_MS;
/**
* The maximum number of jobs we'll attempt to have running at one time. This may occasionally
* be exceeded based on other factors.
*/
private int mSteadyStateConcurrencyLimit = DEFAULT_CONCURRENCY_LIMIT;
/**
* The maximum number of expedited jobs a single userId-package can have running simultaneously.
* TOP apps are not limited.
@@ -451,7 +497,7 @@ class JobConcurrencyManager {
void onThirdPartyAppsCanStart() {
final IBatteryStats batteryStats = IBatteryStats.Stub.asInterface(
ServiceManager.getService(BatteryStats.SERVICE_NAME));
for (int i = 0; i < STANDARD_CONCURRENCY_LIMIT; i++) {
for (int i = 0; i < mSteadyStateConcurrencyLimit; ++i) {
mIdleContexts.add(
mInjector.createJobServiceContext(mService, this,
mNotificationCoordinator, batteryStats,
@@ -778,13 +824,14 @@ class JobConcurrencyManager {
}
preferredUidOnly.sort(sDeterminationComparator);
stoppable.sort(sDeterminationComparator);
for (int i = numRunningJobs; i < STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = numRunningJobs; i < mSteadyStateConcurrencyLimit; ++i) {
final JobServiceContext jsc;
final int numIdleContexts = mIdleContexts.size();
if (numIdleContexts > 0) {
jsc = mIdleContexts.removeAt(numIdleContexts - 1);
} else {
Slog.wtf(TAG, "Had fewer than " + STANDARD_CONCURRENCY_LIMIT + " in existence");
// This could happen if the config is changed at runtime.
Slog.w(TAG, "Had fewer than " + mSteadyStateConcurrencyLimit + " in existence");
jsc = createNewJobServiceContext();
}
@@ -850,7 +897,7 @@ class JobConcurrencyManager {
ContextAssignment selectedContext = null;
final int allWorkTypes = getJobWorkTypes(nextPending);
final boolean pkgConcurrencyOkay = !isPkgConcurrencyLimitedLocked(nextPending);
final boolean isInOverage = projectedRunningCount > STANDARD_CONCURRENCY_LIMIT;
final boolean isInOverage = projectedRunningCount > mSteadyStateConcurrencyLimit;
boolean startingJob = false;
if (idle.size() > 0) {
final int idx = idle.size() - 1;
@@ -1398,7 +1445,7 @@ class JobConcurrencyManager {
noteConcurrency();
return;
}
if (mActiveServices.size() >= STANDARD_CONCURRENCY_LIMIT) {
if (mActiveServices.size() >= mSteadyStateConcurrencyLimit) {
final boolean respectConcurrencyLimit;
if (!mMaxWaitTimeBypassEnabled) {
respectConcurrencyLimit = true;
@@ -1801,23 +1848,27 @@ class JobConcurrencyManager {
DeviceConfig.Properties properties =
DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER);
// Concurrency limit should be in the range [8, MAX_CONCURRENCY_LIMIT].
mSteadyStateConcurrencyLimit = Math.max(8, Math.min(MAX_CONCURRENCY_LIMIT,
properties.getInt(KEY_CONCURRENCY_LIMIT, DEFAULT_CONCURRENCY_LIMIT)));
mScreenOffAdjustmentDelayMs = properties.getLong(
KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS, DEFAULT_SCREEN_OFF_ADJUSTMENT_DELAY_MS);
CONFIG_LIMITS_SCREEN_ON.normal.update(properties);
CONFIG_LIMITS_SCREEN_ON.moderate.update(properties);
CONFIG_LIMITS_SCREEN_ON.low.update(properties);
CONFIG_LIMITS_SCREEN_ON.critical.update(properties);
CONFIG_LIMITS_SCREEN_ON.normal.update(properties, mSteadyStateConcurrencyLimit);
CONFIG_LIMITS_SCREEN_ON.moderate.update(properties, mSteadyStateConcurrencyLimit);
CONFIG_LIMITS_SCREEN_ON.low.update(properties, mSteadyStateConcurrencyLimit);
CONFIG_LIMITS_SCREEN_ON.critical.update(properties, mSteadyStateConcurrencyLimit);
CONFIG_LIMITS_SCREEN_OFF.normal.update(properties);
CONFIG_LIMITS_SCREEN_OFF.moderate.update(properties);
CONFIG_LIMITS_SCREEN_OFF.low.update(properties);
CONFIG_LIMITS_SCREEN_OFF.critical.update(properties);
CONFIG_LIMITS_SCREEN_OFF.normal.update(properties, mSteadyStateConcurrencyLimit);
CONFIG_LIMITS_SCREEN_OFF.moderate.update(properties, mSteadyStateConcurrencyLimit);
CONFIG_LIMITS_SCREEN_OFF.low.update(properties, mSteadyStateConcurrencyLimit);
CONFIG_LIMITS_SCREEN_OFF.critical.update(properties, mSteadyStateConcurrencyLimit);
// Package concurrency limits must in the range [1, STANDARD_CONCURRENCY_LIMIT].
mPkgConcurrencyLimitEj = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
// Package concurrency limits must in the range [1, mSteadyStateConcurrencyLimit].
mPkgConcurrencyLimitEj = Math.max(1, Math.min(mSteadyStateConcurrencyLimit,
properties.getInt(KEY_PKG_CONCURRENCY_LIMIT_EJ, DEFAULT_PKG_CONCURRENCY_LIMIT_EJ)));
mPkgConcurrencyLimitRegular = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
mPkgConcurrencyLimitRegular = Math.max(1, Math.min(mSteadyStateConcurrencyLimit,
properties.getInt(
KEY_PKG_CONCURRENCY_LIMIT_REGULAR, DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR)));
@@ -1838,6 +1889,7 @@ class JobConcurrencyManager {
try {
pw.println("Configuration:");
pw.increaseIndent();
pw.print(KEY_CONCURRENCY_LIMIT, mSteadyStateConcurrencyLimit).println();
pw.print(KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS, mScreenOffAdjustmentDelayMs).println();
pw.print(KEY_PKG_CONCURRENCY_LIMIT_EJ, mPkgConcurrencyLimitEj).println();
pw.print(KEY_PKG_CONCURRENCY_LIMIT_REGULAR, mPkgConcurrencyLimitRegular).println();
@@ -2041,130 +2093,181 @@ class JobConcurrencyManager {
@VisibleForTesting
static class WorkTypeConfig {
@VisibleForTesting
static final String KEY_PREFIX_MAX = CONFIG_KEY_PREFIX_CONCURRENCY + "max_";
@VisibleForTesting
static final String KEY_PREFIX_MIN = CONFIG_KEY_PREFIX_CONCURRENCY + "min_";
private static final String KEY_PREFIX_MAX = CONFIG_KEY_PREFIX_CONCURRENCY + "max_";
private static final String KEY_PREFIX_MIN = CONFIG_KEY_PREFIX_CONCURRENCY + "min_";
@VisibleForTesting
static final String KEY_PREFIX_MAX_TOTAL = CONFIG_KEY_PREFIX_CONCURRENCY + "max_total_";
private static final String KEY_PREFIX_MAX_TOP = CONFIG_KEY_PREFIX_CONCURRENCY + "max_top_";
private static final String KEY_PREFIX_MAX_FGS = CONFIG_KEY_PREFIX_CONCURRENCY + "max_fgs_";
private static final String KEY_PREFIX_MAX_EJ = CONFIG_KEY_PREFIX_CONCURRENCY + "max_ej_";
private static final String KEY_PREFIX_MAX_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "max_bg_";
private static final String KEY_PREFIX_MAX_BGUSER =
CONFIG_KEY_PREFIX_CONCURRENCY + "max_bguser_";
private static final String KEY_PREFIX_MAX_BGUSER_IMPORTANT =
CONFIG_KEY_PREFIX_CONCURRENCY + "max_bguser_important_";
private static final String KEY_PREFIX_MIN_TOP = CONFIG_KEY_PREFIX_CONCURRENCY + "min_top_";
private static final String KEY_PREFIX_MIN_FGS = CONFIG_KEY_PREFIX_CONCURRENCY + "min_fgs_";
private static final String KEY_PREFIX_MIN_EJ = CONFIG_KEY_PREFIX_CONCURRENCY + "min_ej_";
private static final String KEY_PREFIX_MIN_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "min_bg_";
private static final String KEY_PREFIX_MIN_BGUSER =
CONFIG_KEY_PREFIX_CONCURRENCY + "min_bguser_";
private static final String KEY_PREFIX_MIN_BGUSER_IMPORTANT =
CONFIG_KEY_PREFIX_CONCURRENCY + "min_bguser_important_";
@VisibleForTesting
static final String KEY_PREFIX_MAX_RATIO = KEY_PREFIX_MAX + "ratio_";
private static final String KEY_PREFIX_MAX_RATIO_TOP = KEY_PREFIX_MAX_RATIO + "top_";
private static final String KEY_PREFIX_MAX_RATIO_FGS = KEY_PREFIX_MAX_RATIO + "fgs_";
private static final String KEY_PREFIX_MAX_RATIO_EJ = KEY_PREFIX_MAX_RATIO + "ej_";
private static final String KEY_PREFIX_MAX_RATIO_BG = KEY_PREFIX_MAX_RATIO + "bg_";
private static final String KEY_PREFIX_MAX_RATIO_BGUSER = KEY_PREFIX_MAX_RATIO + "bguser_";
private static final String KEY_PREFIX_MAX_RATIO_BGUSER_IMPORTANT =
KEY_PREFIX_MAX_RATIO + "bguser_important_";
@VisibleForTesting
static final String KEY_PREFIX_MIN_RATIO = KEY_PREFIX_MIN + "ratio_";
private static final String KEY_PREFIX_MIN_RATIO_TOP = KEY_PREFIX_MIN_RATIO + "top_";
private static final String KEY_PREFIX_MIN_RATIO_FGS = KEY_PREFIX_MIN_RATIO + "fgs_";
private static final String KEY_PREFIX_MIN_RATIO_EJ = KEY_PREFIX_MIN_RATIO + "ej_";
private static final String KEY_PREFIX_MIN_RATIO_BG = KEY_PREFIX_MIN_RATIO + "bg_";
private static final String KEY_PREFIX_MIN_RATIO_BGUSER = KEY_PREFIX_MIN_RATIO + "bguser_";
private static final String KEY_PREFIX_MIN_RATIO_BGUSER_IMPORTANT =
KEY_PREFIX_MIN_RATIO + "bguser_important_";
private final String mConfigIdentifier;
private int mMaxTotal;
private final SparseIntArray mMinReservedSlots = new SparseIntArray(NUM_WORK_TYPES);
private final SparseIntArray mMaxAllowedSlots = new SparseIntArray(NUM_WORK_TYPES);
private final int mDefaultMaxTotal;
private final SparseIntArray mDefaultMinReservedSlots = new SparseIntArray(NUM_WORK_TYPES);
private final SparseIntArray mDefaultMaxAllowedSlots = new SparseIntArray(NUM_WORK_TYPES);
// We use SparseIntArrays to store floats because there is currently no SparseFloatArray
// available, and it doesn't seem worth it to add such a data structure just for this
// use case. We don't use SparseDoubleArrays because DeviceConfig only supports floats and
// converting between floats and ints is more straightforward than floats and doubles.
private final SparseIntArray mDefaultMinReservedSlotsRatio =
new SparseIntArray(NUM_WORK_TYPES);
private final SparseIntArray mDefaultMaxAllowedSlotsRatio =
new SparseIntArray(NUM_WORK_TYPES);
WorkTypeConfig(@NonNull String configIdentifier, int defaultMaxTotal,
List<Pair<Integer, Integer>> defaultMin, List<Pair<Integer, Integer>> defaultMax) {
WorkTypeConfig(@NonNull String configIdentifier,
int steadyStateConcurrencyLimit, int defaultMaxTotal,
List<Pair<Integer, Float>> defaultMinRatio,
List<Pair<Integer, Float>> defaultMaxRatio) {
mConfigIdentifier = configIdentifier;
mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, STANDARD_CONCURRENCY_LIMIT);
mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, steadyStateConcurrencyLimit);
int numReserved = 0;
for (int i = defaultMin.size() - 1; i >= 0; --i) {
mDefaultMinReservedSlots.put(defaultMin.get(i).first, defaultMin.get(i).second);
numReserved += defaultMin.get(i).second;
for (int i = defaultMinRatio.size() - 1; i >= 0; --i) {
final float ratio = defaultMinRatio.get(i).second;
final int wt = defaultMinRatio.get(i).first;
if (ratio < 0 || 1 <= ratio) {
// 1 means to reserve everything. This shouldn't be allowed.
// We only create new configs on boot, so this should trigger during development
// (before the code gets checked in), so this makes sure the hard-coded defaults
// make sense. DeviceConfig values will be handled gracefully in update().
throw new IllegalArgumentException("Invalid default min ratio: wt=" + wt
+ " minRatio=" + ratio);
}
mDefaultMinReservedSlotsRatio.put(wt, Float.floatToRawIntBits(ratio));
numReserved += mMaxTotal * ratio;
}
if (mDefaultMaxTotal < 0 || numReserved > mDefaultMaxTotal) {
// We only create new configs on boot, so this should trigger during development
// (before the code gets checked in), so this makes sure the hard-coded defaults
// make sense. DeviceConfig values will be handled gracefully in update().
throw new IllegalArgumentException("Invalid default config: t=" + defaultMaxTotal
+ " min=" + defaultMin + " max=" + defaultMax);
+ " min=" + defaultMinRatio + " max=" + defaultMaxRatio);
}
for (int i = defaultMax.size() - 1; i >= 0; --i) {
mDefaultMaxAllowedSlots.put(defaultMax.get(i).first, defaultMax.get(i).second);
for (int i = defaultMaxRatio.size() - 1; i >= 0; --i) {
final float ratio = defaultMaxRatio.get(i).second;
final int wt = defaultMaxRatio.get(i).first;
final float minRatio =
Float.intBitsToFloat(mDefaultMinReservedSlotsRatio.get(wt, 0));
if (ratio < minRatio || ratio <= 0) {
// Max ratio shouldn't be <= 0 or less than minRatio.
throw new IllegalArgumentException("Invalid default config:"
+ " t=" + defaultMaxTotal
+ " min=" + defaultMinRatio + " max=" + defaultMaxRatio);
}
mDefaultMaxAllowedSlotsRatio.put(wt, Float.floatToRawIntBits(ratio));
}
update(new DeviceConfig.Properties.Builder(
DeviceConfig.NAMESPACE_JOB_SCHEDULER).build());
DeviceConfig.NAMESPACE_JOB_SCHEDULER).build(), steadyStateConcurrencyLimit);
}
void update(@NonNull DeviceConfig.Properties properties) {
// Ensure total in the range [1, STANDARD_CONCURRENCY_LIMIT].
mMaxTotal = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
void update(@NonNull DeviceConfig.Properties properties, int steadyStateConcurrencyLimit) {
// Ensure total in the range [1, mSteadyStateConcurrencyLimit].
mMaxTotal = Math.max(1, Math.min(steadyStateConcurrencyLimit,
properties.getInt(KEY_PREFIX_MAX_TOTAL + mConfigIdentifier, mDefaultMaxTotal)));
final int oneIntBits = Float.floatToIntBits(1);
mMaxAllowedSlots.clear();
// Ensure they're in the range [1, total].
final int maxTop = Math.max(1, Math.min(mMaxTotal,
properties.getInt(KEY_PREFIX_MAX_TOP + mConfigIdentifier,
mDefaultMaxAllowedSlots.get(WORK_TYPE_TOP, mMaxTotal))));
final int maxTop = getMaxValue(properties,
KEY_PREFIX_MAX_RATIO_TOP + mConfigIdentifier, WORK_TYPE_TOP, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_TOP, maxTop);
final int maxFgs = Math.max(1, Math.min(mMaxTotal,
properties.getInt(KEY_PREFIX_MAX_FGS + mConfigIdentifier,
mDefaultMaxAllowedSlots.get(WORK_TYPE_FGS, mMaxTotal))));
final int maxFgs = getMaxValue(properties,
KEY_PREFIX_MAX_RATIO_FGS + mConfigIdentifier, WORK_TYPE_FGS, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_FGS, maxFgs);
final int maxEj = Math.max(1, Math.min(mMaxTotal,
properties.getInt(KEY_PREFIX_MAX_EJ + mConfigIdentifier,
mDefaultMaxAllowedSlots.get(WORK_TYPE_EJ, mMaxTotal))));
final int maxEj = getMaxValue(properties,
KEY_PREFIX_MAX_RATIO_EJ + mConfigIdentifier, WORK_TYPE_EJ, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_EJ, maxEj);
final int maxBg = Math.max(1, Math.min(mMaxTotal,
properties.getInt(KEY_PREFIX_MAX_BG + mConfigIdentifier,
mDefaultMaxAllowedSlots.get(WORK_TYPE_BG, mMaxTotal))));
final int maxBg = getMaxValue(properties,
KEY_PREFIX_MAX_RATIO_BG + mConfigIdentifier, WORK_TYPE_BG, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_BG, maxBg);
final int maxBgUserImp = Math.max(1, Math.min(mMaxTotal,
properties.getInt(KEY_PREFIX_MAX_BGUSER_IMPORTANT + mConfigIdentifier,
mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER_IMPORTANT, mMaxTotal))));
final int maxBgUserImp = getMaxValue(properties,
KEY_PREFIX_MAX_RATIO_BGUSER_IMPORTANT + mConfigIdentifier,
WORK_TYPE_BGUSER_IMPORTANT, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_BGUSER_IMPORTANT, maxBgUserImp);
final int maxBgUser = Math.max(1, Math.min(mMaxTotal,
properties.getInt(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER, mMaxTotal))));
final int maxBgUser = getMaxValue(properties,
KEY_PREFIX_MAX_RATIO_BGUSER + mConfigIdentifier, WORK_TYPE_BGUSER, oneIntBits);
mMaxAllowedSlots.put(WORK_TYPE_BGUSER, maxBgUser);
int remaining = mMaxTotal;
mMinReservedSlots.clear();
// Ensure top is in the range [1, min(maxTop, total)]
final int minTop = Math.max(1, Math.min(Math.min(maxTop, mMaxTotal),
properties.getInt(KEY_PREFIX_MIN_TOP + mConfigIdentifier,
mDefaultMinReservedSlots.get(WORK_TYPE_TOP))));
final int minTop = getMinValue(properties,
KEY_PREFIX_MIN_RATIO_TOP + mConfigIdentifier, WORK_TYPE_TOP,
1, Math.min(maxTop, mMaxTotal));
mMinReservedSlots.put(WORK_TYPE_TOP, minTop);
remaining -= minTop;
// Ensure fgs is in the range [0, min(maxFgs, remaining)]
final int minFgs = Math.max(0, Math.min(Math.min(maxFgs, remaining),
properties.getInt(KEY_PREFIX_MIN_FGS + mConfigIdentifier,
mDefaultMinReservedSlots.get(WORK_TYPE_FGS))));
final int minFgs = getMinValue(properties,
KEY_PREFIX_MIN_RATIO_FGS + mConfigIdentifier, WORK_TYPE_FGS,
0, Math.min(maxFgs, remaining));
mMinReservedSlots.put(WORK_TYPE_FGS, minFgs);
remaining -= minFgs;
// Ensure ej is in the range [0, min(maxEj, remaining)]
final int minEj = Math.max(0, Math.min(Math.min(maxEj, remaining),
properties.getInt(KEY_PREFIX_MIN_EJ + mConfigIdentifier,
mDefaultMinReservedSlots.get(WORK_TYPE_EJ))));
final int minEj = getMinValue(properties,
KEY_PREFIX_MIN_RATIO_EJ + mConfigIdentifier, WORK_TYPE_EJ,
0, Math.min(maxEj, remaining));
mMinReservedSlots.put(WORK_TYPE_EJ, minEj);
remaining -= minEj;
// Ensure bg is in the range [0, min(maxBg, remaining)]
final int minBg = Math.max(0, Math.min(Math.min(maxBg, remaining),
properties.getInt(KEY_PREFIX_MIN_BG + mConfigIdentifier,
mDefaultMinReservedSlots.get(WORK_TYPE_BG))));
final int minBg = getMinValue(properties,
KEY_PREFIX_MIN_RATIO_BG + mConfigIdentifier, WORK_TYPE_BG,
0, Math.min(maxBg, remaining));
mMinReservedSlots.put(WORK_TYPE_BG, minBg);
remaining -= minBg;
// Ensure bg user imp is in the range [0, min(maxBgUserImp, remaining)]
final int minBgUserImp = Math.max(0, Math.min(Math.min(maxBgUserImp, remaining),
properties.getInt(KEY_PREFIX_MIN_BGUSER_IMPORTANT + mConfigIdentifier,
mDefaultMinReservedSlots.get(WORK_TYPE_BGUSER_IMPORTANT, 0))));
final int minBgUserImp = getMinValue(properties,
KEY_PREFIX_MIN_RATIO_BGUSER_IMPORTANT + mConfigIdentifier,
WORK_TYPE_BGUSER_IMPORTANT, 0, Math.min(maxBgUserImp, remaining));
mMinReservedSlots.put(WORK_TYPE_BGUSER_IMPORTANT, minBgUserImp);
remaining -= minBgUserImp;
// Ensure bg user is in the range [0, min(maxBgUser, remaining)]
final int minBgUser = Math.max(0, Math.min(Math.min(maxBgUser, remaining),
properties.getInt(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
mDefaultMinReservedSlots.get(WORK_TYPE_BGUSER, 0))));
final int minBgUser = getMinValue(properties,
KEY_PREFIX_MIN_RATIO_BGUSER + mConfigIdentifier, WORK_TYPE_BGUSER,
0, Math.min(maxBgUser, remaining));
mMinReservedSlots.put(WORK_TYPE_BGUSER, minBgUser);
}
/**
* Return the calculated max value for the work type.
* @param defaultFloatInIntBits A {@code float} value in int bits representation (using
* {@link Float#floatToIntBits(float)}.
*/
private int getMaxValue(@NonNull DeviceConfig.Properties properties, @NonNull String key,
int workType, int defaultFloatInIntBits) {
final float maxRatio = Math.min(1, properties.getFloat(key,
Float.intBitsToFloat(
mDefaultMaxAllowedSlotsRatio.get(workType, defaultFloatInIntBits))));
// Max values should be in the range [1, total].
return Math.max(1, (int) (mMaxTotal * maxRatio));
}
/**
* Return the calculated min value for the work type.
*/
private int getMinValue(@NonNull DeviceConfig.Properties properties, @NonNull String key,
int workType, int lowerLimit, int upperLimit) {
final float minRatio = Math.min(1,
properties.getFloat(key,
Float.intBitsToFloat(mDefaultMinReservedSlotsRatio.get(workType))));
return Math.max(lowerLimit, Math.min(upperLimit, (int) (mMaxTotal * minRatio)));
}
int getMaxTotal() {
return mMaxTotal;
}
@@ -2179,29 +2282,37 @@ class JobConcurrencyManager {
void dump(IndentingPrintWriter pw) {
pw.print(KEY_PREFIX_MAX_TOTAL + mConfigIdentifier, mMaxTotal).println();
pw.print(KEY_PREFIX_MIN_TOP + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_TOP))
pw.print(KEY_PREFIX_MIN_RATIO_TOP + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_TOP))
.println();
pw.print(KEY_PREFIX_MAX_TOP + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_TOP))
pw.print(KEY_PREFIX_MAX_RATIO_TOP + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_TOP))
.println();
pw.print(KEY_PREFIX_MIN_FGS + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_FGS))
pw.print(KEY_PREFIX_MIN_RATIO_FGS + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_FGS))
.println();
pw.print(KEY_PREFIX_MAX_FGS + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_FGS))
pw.print(KEY_PREFIX_MAX_RATIO_FGS + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_FGS))
.println();
pw.print(KEY_PREFIX_MIN_EJ + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_EJ))
pw.print(KEY_PREFIX_MIN_RATIO_EJ + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_EJ))
.println();
pw.print(KEY_PREFIX_MAX_EJ + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_EJ))
pw.print(KEY_PREFIX_MAX_RATIO_EJ + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_EJ))
.println();
pw.print(KEY_PREFIX_MIN_BG + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_BG))
pw.print(KEY_PREFIX_MIN_RATIO_BG + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_BG))
.println();
pw.print(KEY_PREFIX_MAX_BG + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_BG))
pw.print(KEY_PREFIX_MAX_RATIO_BG + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_BG))
.println();
pw.print(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
pw.print(KEY_PREFIX_MIN_RATIO_BGUSER + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_BGUSER_IMPORTANT)).println();
pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
pw.print(KEY_PREFIX_MAX_RATIO_BGUSER + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_BGUSER_IMPORTANT)).println();
pw.print(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
pw.print(KEY_PREFIX_MIN_RATIO_BGUSER + mConfigIdentifier,
mMinReservedSlots.get(WORK_TYPE_BGUSER)).println();
pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
pw.print(KEY_PREFIX_MAX_RATIO_BGUSER + mConfigIdentifier,
mMaxAllowedSlots.get(WORK_TYPE_BGUSER)).println();
}
}

View File

@@ -213,7 +213,7 @@ public final class JobConcurrencyManagerTest {
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, idle.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, idle.size());
assertEquals(0, preferredUidOnly.size());
assertEquals(0, stoppable.size());
assertEquals(0, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
@@ -222,7 +222,7 @@ public final class JobConcurrencyManagerTest {
@Test
public void testPrepareForAssignmentDetermination_onlyPendingJobs() {
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
mPendingJobQueue.add(job);
}
@@ -235,7 +235,7 @@ public final class JobConcurrencyManagerTest {
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, idle.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, idle.size());
assertEquals(0, preferredUidOnly.size());
assertEquals(0, stoppable.size());
assertEquals(0, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
@@ -244,7 +244,7 @@ public final class JobConcurrencyManagerTest {
@Test
public void testPrepareForAssignmentDetermination_onlyPreferredUidOnly() {
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
mJobConcurrencyManager.addRunningJobForTesting(job);
}
@@ -262,7 +262,7 @@ public final class JobConcurrencyManagerTest {
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(0, idle.size());
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(0, stoppable.size());
assertEquals(0, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
assertEquals(0, assignmentInfo.numRunningImmediacyPrivileged);
@@ -270,7 +270,7 @@ public final class JobConcurrencyManagerTest {
@Test
public void testPrepareForAssignmentDetermination_onlyStartedWithImmediacyPrivilege() {
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
job.startedWithImmediacyPrivilege = true;
mJobConcurrencyManager.addRunningJobForTesting(job);
@@ -289,19 +289,19 @@ public final class JobConcurrencyManagerTest {
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(0, idle.size());
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT / 2, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT / 2, stoppable.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT / 2, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT / 2, stoppable.size());
assertEquals(0, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
assignmentInfo.numRunningImmediacyPrivileged);
}
@Test
public void testDetermineAssignments_allRegular() throws Exception {
setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT));
setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT));
final ArraySet<JobStatus> jobs = new ArraySet<>();
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
final int uid = mDefaultUserId * UserHandle.PER_USER_RANGE + i;
final String sourcePkgName = "com.source.package." + UserHandle.getAppId(uid);
setPackageUid(sourcePkgName, uid);
@@ -322,7 +322,7 @@ public final class JobConcurrencyManagerTest {
.determineAssignmentsLocked(changed, idle, preferredUidOnly, stoppable,
assignmentInfo);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, changed.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, changed.size());
for (int i = changed.size() - 1; i >= 0; --i) {
jobs.remove(changed.valueAt(i).newJob);
}
@@ -332,16 +332,16 @@ public final class JobConcurrencyManagerTest {
@Test
public void testDetermineAssignments_allPreferredUidOnly_shortTimeLeft() throws Exception {
mConfigBuilder.setBoolean(JobConcurrencyManager.KEY_ENABLE_MAX_WAIT_TIME_BYPASS, true);
setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT));
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT * 2; ++i) {
setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT));
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT * 2; ++i) {
final int uid = mDefaultUserId * UserHandle.PER_USER_RANGE + i;
final String sourcePkgName = "com.source.package." + UserHandle.getAppId(uid);
setPackageUid(sourcePkgName, uid);
final JobStatus job = createJob(uid, sourcePkgName);
spyOn(job);
doReturn(i % 2 == 0).when(job).shouldTreatAsExpeditedJob();
if (i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT) {
if (i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT) {
mJobConcurrencyManager.addRunningJobForTesting(job);
} else {
mPendingJobQueue.add(job);
@@ -366,30 +366,30 @@ public final class JobConcurrencyManagerTest {
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(remainingTimeMs, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
mJobConcurrencyManager
.determineAssignmentsLocked(changed, idle, preferredUidOnly, stoppable,
assignmentInfo);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(0, changed.size());
}
@Test
public void testDetermineAssignments_allPreferredUidOnly_mediumTimeLeft() throws Exception {
mConfigBuilder.setBoolean(JobConcurrencyManager.KEY_ENABLE_MAX_WAIT_TIME_BYPASS, true);
setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT));
setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT));
final ArraySet<JobStatus> jobs = new ArraySet<>();
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT * 2; ++i) {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT * 2; ++i) {
final int uid = mDefaultUserId * UserHandle.PER_USER_RANGE + i;
final String sourcePkgName = "com.source.package." + UserHandle.getAppId(uid);
setPackageUid(sourcePkgName, uid);
final JobStatus job = createJob(uid, sourcePkgName);
spyOn(job);
doReturn(i % 2 == 0).when(job).shouldTreatAsExpeditedJob();
if (i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT) {
if (i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT) {
mJobConcurrencyManager.addRunningJobForTesting(job);
} else {
mPendingJobQueue.add(job);
@@ -417,17 +417,17 @@ public final class JobConcurrencyManagerTest {
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(remainingTimeMs, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
mJobConcurrencyManager
.determineAssignmentsLocked(changed, idle, preferredUidOnly, stoppable,
assignmentInfo);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
for (int i = changed.size() - 1; i >= 0; --i) {
jobs.remove(changed.valueAt(i).newJob);
}
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT - 1, jobs.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT - 1, jobs.size());
assertEquals(1, changed.size());
JobStatus assignedJob = changed.valueAt(0).newJob;
assertTrue(assignedJob.shouldTreatAsExpeditedJob());
@@ -436,17 +436,17 @@ public final class JobConcurrencyManagerTest {
@Test
public void testDetermineAssignments_allPreferredUidOnly_longTimeLeft() throws Exception {
mConfigBuilder.setBoolean(JobConcurrencyManager.KEY_ENABLE_MAX_WAIT_TIME_BYPASS, true);
setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT,
new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT));
setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT,
new TypeConfig(WORK_TYPE_BG, 0, JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT));
final ArraySet<JobStatus> jobs = new ArraySet<>();
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT * 2; ++i) {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT * 2; ++i) {
final int uid = mDefaultUserId * UserHandle.PER_USER_RANGE + i;
final String sourcePkgName = "com.source.package." + UserHandle.getAppId(uid);
setPackageUid(sourcePkgName, uid);
final JobStatus job = createJob(uid, sourcePkgName);
spyOn(job);
doReturn(i % 2 == 0).when(job).shouldTreatAsExpeditedJob();
if (i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT) {
if (i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT) {
mJobConcurrencyManager.addRunningJobForTesting(job);
} else {
mPendingJobQueue.add(job);
@@ -473,13 +473,13 @@ public final class JobConcurrencyManagerTest {
mJobConcurrencyManager.prepareForAssignmentDeterminationLocked(
idle, preferredUidOnly, stoppable, assignmentInfo);
assertEquals(remainingTimeMs, assignmentInfo.minPreferredUidOnlyWaitingTimeMs);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
mJobConcurrencyManager
.determineAssignmentsLocked(changed, idle, preferredUidOnly, stoppable,
assignmentInfo);
assertEquals(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT, preferredUidOnly.size());
assertEquals(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT, preferredUidOnly.size());
// Depending on iteration order, we may create 1 or 2 contexts.
final long numAssignedJobs = changed.size();
assertTrue(numAssignedJobs > 0);
@@ -488,7 +488,7 @@ public final class JobConcurrencyManagerTest {
jobs.remove(changed.valueAt(i).newJob);
}
assertEquals(numAssignedJobs,
JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT - jobs.size());
JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT - jobs.size());
JobStatus firstAssignedJob = changed.valueAt(0).newJob;
if (!firstAssignedJob.shouldTreatAsExpeditedJob()) {
assertEquals(2, numAssignedJobs);
@@ -538,14 +538,14 @@ public final class JobConcurrencyManagerTest {
assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob));
// Pending jobs shouldn't affect TOP job's status.
for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 1; i <= JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
mPendingJobQueue.add(job);
}
assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob));
// Already running jobs shouldn't affect TOP job's status.
for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 1; i <= JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE, i);
mJobConcurrencyManager.addRunningJobForTesting(job);
}
@@ -605,9 +605,9 @@ public final class JobConcurrencyManagerTest {
spyOn(testEj);
doReturn(true).when(testEj).shouldTreatAsExpeditedJob();
setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT);
setConcurrencyConfig(JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT);
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i, i + 1);
mPendingJobQueue.add(job);
}
@@ -887,12 +887,14 @@ public final class JobConcurrencyManagerTest {
mConfigBuilder
.setInt(WorkTypeConfig.KEY_PREFIX_MAX_TOTAL + identifier, total);
for (TypeConfig config : typeConfigs) {
mConfigBuilder.setInt(
WorkTypeConfig.KEY_PREFIX_MAX + config.workTypeString + "_" + identifier,
config.max);
mConfigBuilder.setInt(
WorkTypeConfig.KEY_PREFIX_MIN + config.workTypeString + "_" + identifier,
config.min);
mConfigBuilder.setFloat(
WorkTypeConfig.KEY_PREFIX_MAX_RATIO + config.workTypeString + "_"
+ identifier,
(float) config.max / total);
mConfigBuilder.setFloat(
WorkTypeConfig.KEY_PREFIX_MIN_RATIO + config.workTypeString + "_"
+ identifier,
(float) config.min / total);
}
}
updateDeviceConfig();

View File

@@ -57,14 +57,14 @@ public class BiasSchedulingTest extends AndroidTestCase {
}
public void testLowerBiasJobPreempted() throws Exception {
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 0; i < JobConcurrencyManager.MAX_CONCURRENCY_LIMIT; ++i) {
JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent)
.setBias(LOW_BIAS)
.setOverrideDeadline(0)
.build();
mJobScheduler.schedule(job);
}
final int higherBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT;
final int higherBiasJobId = 100 + JobConcurrencyManager.MAX_CONCURRENCY_LIMIT;
JobInfo jobHigher = new JobInfo.Builder(higherBiasJobId, sJobServiceComponent)
.setBias(HIGH_BIAS)
.setMinimumLatency(2000)
@@ -88,14 +88,14 @@ public class BiasSchedulingTest extends AndroidTestCase {
}
public void testHigherBiasJobNotPreempted() throws Exception {
for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
for (int i = 0; i < JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT; ++i) {
JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent)
.setBias(HIGH_BIAS)
.setOverrideDeadline(0)
.build();
mJobScheduler.schedule(job);
}
final int lowerBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT;
final int lowerBiasJobId = 100 + JobConcurrencyManager.DEFAULT_CONCURRENCY_LIMIT;
JobInfo jobLower = new JobInfo.Builder(lowerBiasJobId, sJobServiceComponent)
.setBias(LOW_BIAS)
.setMinimumLatency(2000)

View File

@@ -16,6 +16,7 @@
package com.android.server.job;
import static com.android.server.job.JobConcurrencyManager.MAX_CONCURRENCY_LIMIT;
import static com.android.server.job.JobConcurrencyManager.NUM_WORK_TYPES;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BG;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BGUSER;
@@ -191,10 +192,10 @@ public class WorkCountTrackerTest {
}
private void recount(Jobs jobs, int totalMax,
@NonNull List<Pair<Integer, Integer>> minLimits,
@NonNull List<Pair<Integer, Integer>> maxLimits) {
@NonNull List<Pair<Integer, Float>> minLimitRatios,
@NonNull List<Pair<Integer, Float>> maxLimitRatios) {
mWorkCountTracker.setConfig(new JobConcurrencyManager.WorkTypeConfig(
"test", totalMax, minLimits, maxLimits));
"test", MAX_CONCURRENCY_LIMIT, totalMax, minLimitRatios, maxLimitRatios));
mWorkCountTracker.resetCounts();
for (int i = 0; i < jobs.running.size(); ++i) {
@@ -259,18 +260,18 @@ public class WorkCountTrackerTest {
* Used by the following testRandom* tests.
*/
private void checkRandom(Jobs jobs, int numTests, int totalMax,
@NonNull List<Pair<Integer, Integer>> minLimits,
@NonNull List<Pair<Integer, Integer>> maxLimits,
@NonNull List<Pair<Integer, Float>> minLimitRatios,
@NonNull List<Pair<Integer, Float>> maxLimitRatios,
double probStart, double[] typeCdf, double[] numTypesCdf, double probStop) {
int minExpected = 0;
for (Pair<Integer, Integer> minLimit : minLimits) {
minExpected = Math.min(minLimit.second, minExpected);
for (Pair<Integer, Float> minLimit : minLimitRatios) {
minExpected = Math.min((int) (minLimit.second * MAX_CONCURRENCY_LIMIT), minExpected);
}
for (int i = 0; i < numTests; i++) {
jobs.maybeFinishJobs(probStop);
jobs.maybeEnqueueJobs(probStart, typeCdf, numTypesCdf);
recount(jobs, totalMax, minLimits, maxLimits);
recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
final int numPending = jobs.pendingMultiTypes.size();
startPendingJobs(jobs);
@@ -284,9 +285,11 @@ public class WorkCountTrackerTest {
}
assertThat(totalRunning).isAtMost(totalMax);
assertThat(totalRunning).isAtLeast(Math.min(minExpected, numPending));
for (Pair<Integer, Integer> maxLimit : maxLimits) {
assertWithMessage("Work type " + maxLimit.first + " is running too many jobs")
.that(jobs.running.get(maxLimit.first)).isAtMost(maxLimit.second);
for (Pair<Integer, Float> maxLimitRatio : maxLimitRatios) {
final int workType = maxLimitRatio.first;
final int maxLimit = (int) (maxLimitRatio.second * MAX_CONCURRENCY_LIMIT);
assertWithMessage("Work type " + workType + " is running too many jobs")
.that(jobs.running.get(workType)).isAtMost(maxLimit);
}
}
}
@@ -302,12 +305,14 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3));
final double probStop = 0.1;
final double probStart = 0.1;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
EQUAL_PROBABILITY_CDF, EQUAL_PROBABILITY_CDF, probStop);
}
@@ -317,15 +322,15 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 2;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Integer>> minLimits = List.of();
final List<Pair<Integer, Float>> minLimitRatios = List.of();
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, .5f));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0, 0.5, 0, 0);
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -335,15 +340,15 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 2;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios = List.of(Pair.create(WORK_TYPE_BG, .99f));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, .5f));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 0, 1.0 / 3);
final double[] numTypesCdf = buildCdf(.75, .2, .05);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -353,15 +358,15 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 10;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Integer>> minLimits = List.of();
final List<Pair<Integer, Float>> minLimitRatios = List.of();
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, .2f), Pair.create(WORK_TYPE_BGUSER, .1f));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 0, 1.0 / 3);
final double[] numTypesCdf = buildCdf(.05, .95);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -371,15 +376,17 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 2.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.8, 0.02, .08);
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -389,15 +396,17 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0.85, 0.05, 0, 0.1, 0, 0);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -407,15 +416,17 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.1, 0.05, .75);
final double[] numTypesCdf = buildCdf(0.5, 0.5);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -425,16 +436,18 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.8, 0.1, 0, 0.05, 0, 0.05);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -444,16 +457,18 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.5, 0, 0.5);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -463,16 +478,18 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.1, 0, 0.9);
final double[] numTypesCdf = buildCdf(0.9, 0.1);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -482,16 +499,18 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3));
final double probStop = 0.5;
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.9, 0, 0.1);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -501,15 +520,16 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 1.0f / 3), Pair.create(WORK_TYPE_BG, 1.0f / 3));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0.5, 0, 0, 0);
final double[] numTypesCdf = buildCdf(0.1, 0.7, 0.2);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -522,16 +542,16 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 13;
final List<Pair<Integer, Integer>> maxLimits = List.of(
Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4),
Pair.create(WORK_TYPE_BGUSER, 3));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 2.0f / 13), Pair.create(WORK_TYPE_BG, 1.0f / 13));
final List<Pair<Integer, Float>> maxLimitRatios = List.of(
Pair.create(WORK_TYPE_EJ, 5.0f / 13), Pair.create(WORK_TYPE_BG, 4.0f / 13),
Pair.create(WORK_TYPE_BGUSER, 3.0f / 13));
final double probStop = 0.13;
final double[] numTypesCdf = buildCdf(0, 0.05, 0.1, 0.7, 0.1, 0.05);
final double probStart = 0.87;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
EQUAL_PROBABILITY_CDF, numTypesCdf, probStop);
}
@@ -541,15 +561,16 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 5.0f / 6), Pair.create(WORK_TYPE_BG, 2.0f / 3));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(.1, 0, 0.5, 0.35, 0, 0.05);
final double[] numTypesCdf = buildCdf(1);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -559,17 +580,17 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 6;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4),
Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, .5f), Pair.create(WORK_TYPE_BG, 1.0f / 3));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 5.0f / 6), Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.4, 0.1, 0, 0.4);
final double[] numTypesCdf = buildCdf(0.7, 0.3);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
@@ -579,25 +600,25 @@ public class WorkCountTrackerTest {
final int numTests = 5000;
final int totalMax = 7;
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 3.0f / 7), Pair.create(WORK_TYPE_BG, 2.0f / 7));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 5.0f / 7), Pair.create(WORK_TYPE_BG, 4.0f / 7),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1.0f / 7),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 7));
final double probStop = 0.4;
final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.25, 0.05, 0.3, 0.3);
final double[] numTypesCdf = buildCdf(0.7, 0.3);
final double probStart = 0.5;
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
checkRandom(jobs, numTests, totalMax, minLimitRatios, maxLimitRatios, probStart,
cdf, numTypesCdf, probStop);
}
/** Used by the following tests */
private void checkSimple(int totalMax,
@NonNull List<Pair<Integer, Integer>> minLimits,
@NonNull List<Pair<Integer, Integer>> maxLimits,
@NonNull List<Pair<Integer, Float>> minLimitRatios,
@NonNull List<Pair<Integer, Float>> maxLimitRatios,
@NonNull List<Pair<Integer, Integer>> running,
@NonNull List<Pair<Integer, Integer>> pending,
@NonNull List<Pair<Integer, Integer>> resultRunning,
@@ -610,17 +631,19 @@ public class WorkCountTrackerTest {
jobs.addPending(pend.first, pend.second);
}
recount(jobs, totalMax, minLimits, maxLimits);
recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
startPendingJobs(jobs);
for (Pair<Integer, Integer> run : resultRunning) {
assertWithMessage(
"Incorrect running result for work type " + workTypeToString(run.first))
"Incorrect running result for work type " + workTypeToString(run.first)
+ " wanted " + run.second + ", got " + jobs.running.get(run.first))
.that(jobs.running.get(run.first)).isEqualTo(run.second);
}
for (Pair<Integer, Integer> pend : resultPending) {
assertWithMessage(
"Incorrect pending result for work type " + workTypeToString(pend.first))
"Incorrect pending result for work type " + workTypeToString(pend.first)
+ " wanted " + pend.second + ", got " + jobs.pending.get(pend.first))
.that(jobs.pending.get(pend.first)).isEqualTo(pend.second);
}
}
@@ -628,16 +651,18 @@ public class WorkCountTrackerTest {
@Test
public void testBasic() {
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 1)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 1)),
/* resPen */ List.of());
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
@@ -645,39 +670,40 @@ public class WorkCountTrackerTest {
// When there are BG jobs pending, 2 (min-BG) jobs should run.
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 1)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 5)));
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 2)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 1)));
checkSimple(8,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(),
/* pen */ List.of(Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_BG, 43)));
checkSimple(8,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 4)),
/* pen */ List.of(Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_BG, 47)));
checkSimple(8,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 4)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 49), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 4)),
@@ -686,48 +712,52 @@ public class WorkCountTrackerTest {
checkSimple(8,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 6)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
/* max */
List.of(Pair.create(WORK_TYPE_TOP, .75f), Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 4)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 4)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 8), Pair.create(WORK_TYPE_BG, 49)));
checkSimple(8,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 6)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .25f)),
/* max */ List.of(
Pair.create(WORK_TYPE_TOP, .75f), Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 1)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 48)));
checkSimple(8,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 8)),
/* max */ List.of(
Pair.create(WORK_TYPE_TOP, .75f), Pair.create(WORK_TYPE_BG, .25f)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 8), Pair.create(WORK_TYPE_BG, 49)));
checkSimple(8,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 8)),
/* max */
List.of(Pair.create(WORK_TYPE_TOP, .75f), Pair.create(WORK_TYPE_BG, .25f)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 8), Pair.create(WORK_TYPE_BG, 49)));
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)),
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)));
checkSimple(8,
/* min */ List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4)),
/* min */ List.of(Pair.create(WORK_TYPE_EJ, .25f), Pair.create(WORK_TYPE_BG, .25f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, .75f)),
/* run */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_EJ, 5),
Pair.create(WORK_TYPE_BG, 3)),
@@ -740,15 +770,16 @@ public class WorkCountTrackerTest {
// shouldn't start new ones.
checkSimple(5,
/* min */ List.of(),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, .2f)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)),
/* resRun */ List.of(Pair.create(WORK_TYPE_BG, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)));
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10),
Pair.create(WORK_TYPE_BG, 3),
@@ -759,8 +790,9 @@ public class WorkCountTrackerTest {
Pair.create(WORK_TYPE_BGUSER, 3)));
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 3)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 2.0f / 3), Pair.create(WORK_TYPE_BGUSER, .5f)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* pen */ List.of(Pair.create(WORK_TYPE_BG, 3), Pair.create(WORK_TYPE_BGUSER, 3)),
/* resRun */ List.of(
@@ -769,8 +801,9 @@ public class WorkCountTrackerTest {
Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1)));
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 1)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6)),
/* run */ List.of(Pair.create(WORK_TYPE_BG, 2)),
/* pen */ List.of(Pair.create(WORK_TYPE_BG, 3), Pair.create(WORK_TYPE_BGUSER, 3)),
/* resRun */ List.of(
@@ -778,12 +811,13 @@ public class WorkCountTrackerTest {
/* resPen */ List.of(
Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 2)));
Log.d(TAG, "START***#*#*#*#*#*#**#*");
// Test multi-types
checkSimple(6,
/* min */ List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2)),
/* min */
List.of(Pair.create(WORK_TYPE_EJ, 1.0f / 3), Pair.create(WORK_TYPE_BG, 1.0f / 3)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 1)),
Pair.create(WORK_TYPE_BG, 2.0f / 3),
Pair.create(WORK_TYPE_BGUSER, 1.0f / 6)),
/* run */ List.of(),
/* pen */ List.of(
// 2 of these as TOP, 1 as EJ
@@ -809,10 +843,12 @@ public class WorkCountTrackerTest {
jobs.addPending(WORK_TYPE_BG, 10);
final int totalMax = 6;
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 1));
final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 5));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 1.0f / totalMax));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 5.0f / totalMax));
recount(jobs, totalMax, minLimits, maxLimits);
recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
startPendingJobs(jobs);
@@ -887,11 +923,12 @@ public class WorkCountTrackerTest {
jobs.addPending(WORK_TYPE_BG, 10); // c
final int totalMax = 8;
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1));
final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 5));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 1.0f / 8), Pair.create(WORK_TYPE_BG, 1.0f / 8));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 5.0f / 8));
recount(jobs, totalMax, minLimits, maxLimits);
recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
assertThat(jobs.pending.get(WORK_TYPE_TOP)).isEqualTo(11);
assertThat(jobs.pending.get(WORK_TYPE_EJ)).isEqualTo(5);
@@ -966,11 +1003,12 @@ public class WorkCountTrackerTest {
}
final int totalMax = 8;
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1));
final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 5));
final List<Pair<Integer, Float>> minLimitRatios =
List.of(Pair.create(WORK_TYPE_EJ, 1.0f / 8), Pair.create(WORK_TYPE_BG, 1.0f / 8));
final List<Pair<Integer, Float>> maxLimitRatios =
List.of(Pair.create(WORK_TYPE_BG, 5.0f / 8));
recount(jobs, totalMax, minLimits, maxLimits);
recount(jobs, totalMax, minLimitRatios, maxLimitRatios);
assertThat(jobs.pending.get(WORK_TYPE_TOP)).isEqualTo(11);
assertThat(jobs.pending.get(WORK_TYPE_EJ)).isEqualTo(10);

View File

@@ -45,23 +45,26 @@ import java.util.List;
@SmallTest
public class WorkTypeConfigTest {
private static final String KEY_MAX_TOTAL = "concurrency_max_total_test";
private static final String KEY_MAX_TOP = "concurrency_max_top_test";
private static final String KEY_MAX_FGS = "concurrency_max_fgs_test";
private static final String KEY_MAX_EJ = "concurrency_max_ej_test";
private static final String KEY_MAX_BG = "concurrency_max_bg_test";
private static final String KEY_MAX_BGUSER_IMPORTANT = "concurrency_max_bguser_important_test";
private static final String KEY_MAX_BGUSER = "concurrency_max_bguser_test";
private static final String KEY_MIN_TOP = "concurrency_min_top_test";
private static final String KEY_MIN_FGS = "concurrency_min_fgs_test";
private static final String KEY_MIN_EJ = "concurrency_min_ej_test";
private static final String KEY_MIN_BG = "concurrency_min_bg_test";
private static final String KEY_MIN_BGUSER_IMPORTANT = "concurrency_min_bguser_important_test";
private static final String KEY_MIN_BGUSER = "concurrency_min_bguser_test";
private static final String KEY_MAX_RATIO_TOP = "concurrency_max_ratio_top_test";
private static final String KEY_MAX_RATIO_FGS = "concurrency_max_ratio_fgs_test";
private static final String KEY_MAX_RATIO_EJ = "concurrency_max_ratio_ej_test";
private static final String KEY_MAX_RATIO_BG = "concurrency_max_ratio_bg_test";
private static final String KEY_MAX_RATIO_BGUSER_IMPORTANT =
"concurrency_max_ratio_bguser_important_test";
private static final String KEY_MAX_RATIO_BGUSER = "concurrency_max_ratio_bguser_test";
private static final String KEY_MIN_RATIO_TOP = "concurrency_min_ratio_top_test";
private static final String KEY_MIN_RATIO_FGS = "concurrency_min_ratio_fgs_test";
private static final String KEY_MIN_RATIO_EJ = "concurrency_min_ratio_ej_test";
private static final String KEY_MIN_RATIO_BG = "concurrency_min_ratio_bg_test";
private static final String KEY_MIN_RATIO_BGUSER_IMPORTANT =
"concurrency_min_ratio_bguser_important_test";
private static final String KEY_MIN_RATIO_BGUSER = "concurrency_min_ratio_bguser_test";
private void check(@Nullable DeviceConfig.Properties config,
int defaultLimit,
int defaultTotal,
@NonNull List<Pair<Integer, Integer>> defaultMin,
@NonNull List<Pair<Integer, Integer>> defaultMax,
@NonNull List<Pair<Integer, Float>> defaultMinRatios,
@NonNull List<Pair<Integer, Float>> defaultMaxRatios,
boolean expectedValid, int expectedTotal,
@NonNull List<Pair<Integer, Integer>> expectedMinLimits,
@NonNull List<Pair<Integer, Integer>> expectedMaxLimits) throws Exception {
@@ -69,7 +72,7 @@ public class WorkTypeConfigTest {
final WorkTypeConfig counts;
try {
counts = new WorkTypeConfig("test",
defaultTotal, defaultMin, defaultMax);
defaultLimit, defaultTotal, defaultMinRatios, defaultMaxRatios);
if (!expectedValid) {
fail("Invalid config successfully created");
return;
@@ -84,7 +87,7 @@ public class WorkTypeConfigTest {
}
if (config != null) {
counts.update(config);
counts.update(config, defaultLimit);
}
assertEquals(expectedTotal, counts.getMaxTotal());
@@ -101,7 +104,7 @@ public class WorkTypeConfigTest {
@Test
public void test() throws Exception {
// Tests with various combinations.
check(null, /*default*/ 13,
check(null, /* limit */ 16, /*default*/ 13,
/* min */ List.of(),
/* max */ List.of(),
/*expected*/ true, 13,
@@ -109,111 +112,141 @@ public class WorkTypeConfigTest {
Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 13), Pair.create(WORK_TYPE_EJ, 13),
Pair.create(WORK_TYPE_BG, 13), Pair.create(WORK_TYPE_BGUSER, 13)));
check(null, /*default*/ 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
check(null, /* limit */ 16, /*default*/ 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, .8f), Pair.create(WORK_TYPE_BG, 0f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, .2f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)));
check(null, /*default*/ 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
check(null, /* limit */ 16, /*default*/ 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1f),
Pair.create(WORK_TYPE_BG, 0f), Pair.create(WORK_TYPE_BGUSER, 0f)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 1)),
/*expected*/ true, 5,
Pair.create(WORK_TYPE_BG, 0f), Pair.create(WORK_TYPE_BGUSER, .2f)),
/*expected*/ false, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1)));
check(null, /*default*/ 0,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 0)),
/*expected*/ false, 1,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
check(null, /*default*/ -1,
/* min */ List.of(Pair.create(WORK_TYPE_BG, -1)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, -1)),
/*expected*/ false, 1,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
check(null, /*default*/ 5,
/* min */ List.of(
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 0)),
check(null, /* limit */ 16, /*default*/ 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, .99f),
Pair.create(WORK_TYPE_BG, 0f), Pair.create(WORK_TYPE_BGUSER, 0f)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)),
Pair.create(WORK_TYPE_BG, .01f), Pair.create(WORK_TYPE_BGUSER, .2f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4),
Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1)));
check(null, /* limit */ 16, /*default*/ 0,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1f), Pair.create(WORK_TYPE_BG, 0f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 0f)),
/*expected*/ false, 1,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
check(null, /* limit */ 16, /*default*/ -1,
/* min */ List.of(Pair.create(WORK_TYPE_BG, -1f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, -1f)),
/*expected*/ false, 1,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
check(null, /* limit */ 16, /*default*/ 5,
/* min */ List.of(
Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 0f)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1f)),
/*expected*/ false, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)));
check(null, /* limit */ 16, /*default*/ 5,
/* min */ List.of(
Pair.create(WORK_TYPE_BG, .99f), Pair.create(WORK_TYPE_BGUSER, 0f)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)));
check(null, /*default*/ 6,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 2)),
check(null, /* limit */ 16, /*default*/ 6,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1.0f / 6),
Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1.0f / 3)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 1)),
Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1.0f / 6)),
/*expected*/ false, 6,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 6),
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 1)));
check(null, /*default*/ 4,
check(null, /* limit */ 16, /*default*/ 4,
/* min */ List.of(
Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 6)),
Pair.create(WORK_TYPE_BG, 1.5f), Pair.create(WORK_TYPE_BGUSER, 1.5f)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)),
Pair.create(WORK_TYPE_BG, 1.25f), Pair.create(WORK_TYPE_BGUSER, 1.25f)),
/*expected*/ false, 4,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 3), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 4),
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 4)));
check(null, /*default*/ 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
check(null, /* limit */ 16, /*default*/ 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, .8f), Pair.create(WORK_TYPE_BG, .2f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, .2f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)));
check(null, /*default*/ 10,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 3),
Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
check(null, /* limit */ 16, /*default*/ 10,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, .4f), Pair.create(WORK_TYPE_EJ, .3f),
Pair.create(WORK_TYPE_BG, .1f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, .1f)),
/*expected*/ true, 10,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 3),
Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 1)));
check(null, /*default*/ 10,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 3), Pair.create(WORK_TYPE_FGS, 2),
Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_FGS, 3)),
check(null, /* limit */ 16, /*default*/ 10,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, .3f), Pair.create(WORK_TYPE_FGS, .2f),
Pair.create(WORK_TYPE_EJ, .1f), Pair.create(WORK_TYPE_BG, .1f)),
/* max */ List.of(Pair.create(WORK_TYPE_FGS, .3f)),
/*expected*/ true, 10,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 3), Pair.create(WORK_TYPE_FGS, 2),
Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1)),
/* max */ List.of(Pair.create(WORK_TYPE_FGS, 3)));
check(null, /*default*/ 15,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 15)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 15)),
check(null, /* limit */ 16, /*default*/ 15,
/* min */ List.of(Pair.create(WORK_TYPE_BG, .95f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 15,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 14)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 15), Pair.create(WORK_TYPE_BG, 15)));
check(null, /*default*/ 16,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 16)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 16)),
check(null, /* limit */ 16, /*default*/ 16,
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 15)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
check(null, /*default*/ 20,
check(null, /* limit */ 16, /*default*/ 20,
/* min */ List.of(
Pair.create(WORK_TYPE_BG, 20), Pair.create(WORK_TYPE_BGUSER, 10)),
Pair.create(WORK_TYPE_BG, .99f), Pair.create(WORK_TYPE_BGUSER, .5f)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 20), Pair.create(WORK_TYPE_BGUSER, 20)),
Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1f)),
/*expected*/ false, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 15), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16),
Pair.create(WORK_TYPE_BG, 16), Pair.create(WORK_TYPE_BGUSER, 16)));
check(null, /*default*/ 20,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 16)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 16)),
check(null, /* limit */ 76, /*default*/ 80,
/* min */ List.of(
Pair.create(WORK_TYPE_BG, .98f), Pair.create(WORK_TYPE_BGUSER, .9f)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, 1f)),
/*expected*/ false, 64,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
Pair.create(WORK_TYPE_BG, 63), Pair.create(WORK_TYPE_BGUSER, 0)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 64),
Pair.create(WORK_TYPE_BG, 64), Pair.create(WORK_TYPE_BGUSER, 64)));
check(null, /* limit */ 16, /*default*/ 20,
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 15)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
@@ -221,94 +254,101 @@ public class WorkTypeConfigTest {
// Test for overriding with a setting string.
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 5)
.setInt(KEY_MAX_BG, 4)
.setInt(KEY_MIN_BG, 3)
.setFloat(KEY_MAX_RATIO_BG, .8f)
.setFloat(KEY_MIN_RATIO_BG, .6f)
.build(),
/* limit */ 16,
/*default*/ 9,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(
Pair.create(WORK_TYPE_BG, 9), Pair.create(WORK_TYPE_BGUSER, 2)),
Pair.create(WORK_TYPE_BG, 1f), Pair.create(WORK_TYPE_BGUSER, .4f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 3)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 5).build(),
/* limit */ 16,
/*default*/ 9,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 5,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 4)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 5)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_BG, 4).build(),
.setFloat(KEY_MAX_RATIO_BG, 4.0f / 9).build(),
/* limit */ 16,
/*default*/ 9,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 9,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 4)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 9), Pair.create(WORK_TYPE_BG, 4)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MIN_BG, 3).build(),
.setFloat(KEY_MIN_RATIO_BG, 1.0f / 3).build(),
/* limit */ 16,
/*default*/ 9,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 9,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 3)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 9), Pair.create(WORK_TYPE_BG, 9)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 20)
.setInt(KEY_MAX_EJ, 5)
.setInt(KEY_MIN_EJ, 2)
.setInt(KEY_MAX_BG, 16)
.setInt(KEY_MIN_BG, 8)
.setFloat(KEY_MAX_RATIO_EJ, .25f)
.setFloat(KEY_MIN_RATIO_EJ, .1f)
.setFloat(KEY_MAX_RATIO_BG, .8f)
.setFloat(KEY_MIN_RATIO_BG, .4f)
.build(),
/* limit */ 16,
/*default*/ 9,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_EJ, 2),
Pair.create(WORK_TYPE_BG, 8)),
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_EJ, 1),
Pair.create(WORK_TYPE_BG, 6)),
/* max */
List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_EJ, 5),
Pair.create(WORK_TYPE_BG, 16)));
List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_EJ, 4),
Pair.create(WORK_TYPE_BG, 12)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 20)
.setInt(KEY_MAX_BG, 20)
.setInt(KEY_MIN_BG, 8)
.setFloat(KEY_MAX_RATIO_BG, 1f)
.setFloat(KEY_MIN_RATIO_BG, .4f)
.build(),
/* limit */ 16,
/*default*/ 9,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 8)),
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 6)),
/* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 16)
.setInt(KEY_MAX_TOP, 16)
.setInt(KEY_MIN_TOP, 1)
.setInt(KEY_MAX_FGS, 15)
.setInt(KEY_MIN_FGS, 2)
.setInt(KEY_MAX_EJ, 14)
.setInt(KEY_MIN_EJ, 3)
.setInt(KEY_MAX_BG, 13)
.setInt(KEY_MIN_BG, 4)
.setInt(KEY_MAX_BGUSER_IMPORTANT, 12)
.setInt(KEY_MIN_BGUSER_IMPORTANT, 5)
.setInt(KEY_MAX_BGUSER, 11)
.setInt(KEY_MIN_BGUSER, 6)
.setFloat(KEY_MAX_RATIO_TOP, 1f)
.setFloat(KEY_MIN_RATIO_TOP, 1.0f / 16)
.setFloat(KEY_MAX_RATIO_FGS, 15.0f / 16)
.setFloat(KEY_MIN_RATIO_FGS, 2.0f / 16)
.setFloat(KEY_MAX_RATIO_EJ, 14.0f / 16)
.setFloat(KEY_MIN_RATIO_EJ, 3.0f / 16)
.setFloat(KEY_MAX_RATIO_BG, 13.0f / 16)
.setFloat(KEY_MIN_RATIO_BG, 3.0f / 16)
.setFloat(KEY_MAX_RATIO_BGUSER_IMPORTANT, 12.0f / 16)
.setFloat(KEY_MIN_RATIO_BGUSER_IMPORTANT, 2.0f / 16)
.setFloat(KEY_MAX_RATIO_BGUSER, 11.0f / 16)
.setFloat(KEY_MIN_RATIO_BGUSER, 2.0f / 16)
.build(),
/* limit */ 16,
/*default*/ 9,
/* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
/* min */ List.of(Pair.create(WORK_TYPE_BG, .99f)),
/* max */ List.of(Pair.create(WORK_TYPE_BG, 1f)),
/*expected*/ true, 16,
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_FGS, 2),
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 4),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 5),
Pair.create(WORK_TYPE_BGUSER, 6)),
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 3),
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
Pair.create(WORK_TYPE_BGUSER, 2)),
/* max */
List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_FGS, 15),
Pair.create(WORK_TYPE_EJ, 14), Pair.create(WORK_TYPE_BG, 13),