Adjust concurrency limits based on device.

The concurrency limits haven't really changed much since JobScheduler
was first created. Since we're moving to a world where we want apps to
run jobs instead of FGS, we need to adjust them to handle the new
reality (fewer FGS, more jobs) and make sense given modern device
characteristics. We now set the concurrency limit based on the device's
RAM size and set min and max slots as a percentage of that dynamic
limit.

Bug: 262613827
Test: atest CtsJobSchedulerTestCases:ExpeditedJobTest
Test: atest CtsJobSchedulerTestCases:JobSchedulingTest
Test: atest FrameworksMockingServicesTests:JobConcurrencyManagerTest
Test: atest FrameworksServicesTests:BiasSchedulingTest
Test: atest FrameworksServicesTests:WorkCountTrackerTest
Test: atest FrameworksServicesTests:WorkTypeConfigTest
Change-Id: Ic0aa25f8d2c6af5800f9b33359ac58d1b96435f3
This commit is contained in:
Kweku Adams
2022-12-21 14:54:02 +00:00
parent 404b71818e
commit 4a011591eb
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),