Merge "Make smart idle maint's period changable"

This commit is contained in:
Daeho Jeong
2022-03-25 22:26:12 +00:00
committed by Gerrit Code Review
2 changed files with 59 additions and 37 deletions

View File

@@ -46,7 +46,7 @@ public class SmartStorageMaintIdler extends JobService {
} }
// ... and try again in a next period // ... and try again in a next period
scheduleSmartIdlePass(SmartStorageMaintIdler.this, scheduleSmartIdlePass(SmartStorageMaintIdler.this,
StorageManagerService.SMART_IDLE_MAINT_PERIOD); StorageManagerService.sSmartIdleMaintPeriod);
} }
}; };
@@ -70,7 +70,7 @@ public class SmartStorageMaintIdler extends JobService {
/** /**
* Schedule the smart storage idle maintenance job * Schedule the smart storage idle maintenance job
*/ */
public static void scheduleSmartIdlePass(Context context, int nHours) { public static void scheduleSmartIdlePass(Context context, int nMinutes) {
StorageManagerService ms = StorageManagerService.sSelf; StorageManagerService ms = StorageManagerService.sSelf;
if ((ms == null) || ms.isPassedLifetimeThresh()) { if ((ms == null) || ms.isPassedLifetimeThresh()) {
return; return;
@@ -78,7 +78,7 @@ public class SmartStorageMaintIdler extends JobService {
JobScheduler tm = context.getSystemService(JobScheduler.class); JobScheduler tm = context.getSystemService(JobScheduler.class);
long nextScheduleTime = TimeUnit.HOURS.toMillis(nHours); long nextScheduleTime = TimeUnit.MINUTES.toMillis(nMinutes);
JobInfo.Builder builder = new JobInfo.Builder(SMART_MAINT_JOB_ID, JobInfo.Builder builder = new JobInfo.Builder(SMART_MAINT_JOB_ID,
SMART_STORAGE_MAINT_SERVICE); SMART_STORAGE_MAINT_SERVICE);

View File

@@ -332,13 +332,15 @@ class StorageManagerService extends IStorageManager.Stub
@Nullable public static String sMediaStoreAuthorityProcessName; @Nullable public static String sMediaStoreAuthorityProcessName;
// Run period in hour for smart idle maintenance // Smart idle maintenance running period in minute
static final int SMART_IDLE_MAINT_PERIOD = 1; static volatile int sSmartIdleMaintPeriod = 60;
private final AtomicFile mSettingsFile; private final AtomicFile mSettingsFile;
private final AtomicFile mHourlyWriteFile; private final AtomicFile mWriteRecordFile;
private static final int MAX_HOURLY_WRITE_RECORDS = 72; // 72 hours (3 days)
private static final int MAX_PERIOD_WRITE_RECORD = 72 * 60;
private volatile int mMaxWriteRecords;
/** /**
* Default config values for smart idle maintenance * Default config values for smart idle maintenance
@@ -346,6 +348,10 @@ class StorageManagerService extends IStorageManager.Stub
*/ */
// Decide whether smart idle maintenance is enabled or not // Decide whether smart idle maintenance is enabled or not
private static final boolean DEFAULT_SMART_IDLE_MAINT_ENABLED = false; private static final boolean DEFAULT_SMART_IDLE_MAINT_ENABLED = false;
// Run period in minute for smart idle maintenance
private static final int DEFAULT_SMART_IDLE_MAINT_PERIOD = 60;
private static final int MIN_SMART_IDLE_MAINT_PERIOD = 10;
private static final int MAX_SMART_IDLE_MAINT_PERIOD = 24 * 60;
// Storage lifetime percentage threshold to decide to turn off the feature // Storage lifetime percentage threshold to decide to turn off the feature
private static final int DEFAULT_LIFETIME_PERCENT_THRESHOLD = 70; private static final int DEFAULT_LIFETIME_PERCENT_THRESHOLD = 70;
// Minimum required number of dirty + free segments to trigger GC // Minimum required number of dirty + free segments to trigger GC
@@ -368,8 +374,8 @@ class StorageManagerService extends IStorageManager.Stub
private volatile boolean mNeedGC; private volatile boolean mNeedGC;
private volatile boolean mPassedLifetimeThresh; private volatile boolean mPassedLifetimeThresh;
// Tracking storage hourly write amounts // Tracking storage write amounts in one period
private volatile int[] mStorageHourlyWrites; private volatile int[] mStorageWriteRecords;
/** /**
* <em>Never</em> hold the lock while performing downcalls into vold, since * <em>Never</em> hold the lock while performing downcalls into vold, since
@@ -914,7 +920,7 @@ class StorageManagerService extends IStorageManager.Stub
private void handleSystemReady() { private void handleSystemReady() {
if (prepareSmartIdleMaint()) { if (prepareSmartIdleMaint()) {
SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, SMART_IDLE_MAINT_PERIOD); SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, sSmartIdleMaintPeriod);
} }
// Start scheduling nominally-daily fstrim operations // Start scheduling nominally-daily fstrim operations
@@ -1889,10 +1895,19 @@ class StorageManagerService extends IStorageManager.Stub
mSettingsFile = new AtomicFile( mSettingsFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings"); new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
mHourlyWriteFile = new AtomicFile( mWriteRecordFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "storage-hourly-writes")); new File(Environment.getDataSystemDirectory(), "storage-write-records"));
mStorageHourlyWrites = new int[MAX_HOURLY_WRITE_RECORDS]; sSmartIdleMaintPeriod = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
"smart_idle_maint_period", DEFAULT_SMART_IDLE_MAINT_PERIOD);
if (sSmartIdleMaintPeriod < MIN_SMART_IDLE_MAINT_PERIOD) {
sSmartIdleMaintPeriod = MIN_SMART_IDLE_MAINT_PERIOD;
} else if (sSmartIdleMaintPeriod > MAX_SMART_IDLE_MAINT_PERIOD) {
sSmartIdleMaintPeriod = MAX_SMART_IDLE_MAINT_PERIOD;
}
mMaxWriteRecords = MAX_PERIOD_WRITE_RECORD / sSmartIdleMaintPeriod;
mStorageWriteRecords = new int[mMaxWriteRecords];
synchronized (mLock) { synchronized (mLock) {
readSettingsLocked(); readSettingsLocked();
@@ -2638,7 +2653,7 @@ class StorageManagerService extends IStorageManager.Stub
// maintenance to avoid the conflict // maintenance to avoid the conflict
mNeedGC = false; mNeedGC = false;
loadStorageHourlyWrites(); loadStorageWriteRecords();
try { try {
mVold.refreshLatestWrite(); mVold.refreshLatestWrite();
} catch (Exception e) { } catch (Exception e) {
@@ -2654,13 +2669,17 @@ class StorageManagerService extends IStorageManager.Stub
return mPassedLifetimeThresh; return mPassedLifetimeThresh;
} }
private void loadStorageHourlyWrites() { private void loadStorageWriteRecords() {
FileInputStream fis = null; FileInputStream fis = null;
try { try {
fis = mHourlyWriteFile.openRead(); fis = mWriteRecordFile.openRead();
ObjectInputStream ois = new ObjectInputStream(fis); ObjectInputStream ois = new ObjectInputStream(fis);
mStorageHourlyWrites = (int[])ois.readObject();
int periodValue = ois.readInt();
if (periodValue == sSmartIdleMaintPeriod) {
mStorageWriteRecords = (int[]) ois.readObject();
}
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
// Missing data is okay, probably first boot // Missing data is okay, probably first boot
} catch (Exception e) { } catch (Exception e) {
@@ -2670,24 +2689,26 @@ class StorageManagerService extends IStorageManager.Stub
} }
} }
private int getAverageHourlyWrite() { private int getAverageWriteAmount() {
return Arrays.stream(mStorageHourlyWrites).sum() / MAX_HOURLY_WRITE_RECORDS; return Arrays.stream(mStorageWriteRecords).sum() / mMaxWriteRecords;
} }
private void updateStorageHourlyWrites(int latestWrite) { private void updateStorageWriteRecords(int latestWrite) {
FileOutputStream fos = null; FileOutputStream fos = null;
System.arraycopy(mStorageHourlyWrites,0, mStorageHourlyWrites, 1, System.arraycopy(mStorageWriteRecords, 0, mStorageWriteRecords, 1,
MAX_HOURLY_WRITE_RECORDS - 1); mMaxWriteRecords - 1);
mStorageHourlyWrites[0] = latestWrite; mStorageWriteRecords[0] = latestWrite;
try { try {
fos = mHourlyWriteFile.startWrite(); fos = mWriteRecordFile.startWrite();
ObjectOutputStream oos = new ObjectOutputStream(fos); ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(mStorageHourlyWrites);
mHourlyWriteFile.finishWrite(fos); oos.writeInt(sSmartIdleMaintPeriod);
oos.writeObject(mStorageWriteRecords);
mWriteRecordFile.finishWrite(fos);
} catch (IOException e) { } catch (IOException e) {
if (fos != null) { if (fos != null) {
mHourlyWriteFile.failWrite(fos); mWriteRecordFile.failWrite(fos);
} }
} }
} }
@@ -2751,22 +2772,23 @@ class StorageManagerService extends IStorageManager.Stub
return; return;
} }
int latestHourlyWrite = mVold.getWriteAmount(); int latestWrite = mVold.getWriteAmount();
if (latestHourlyWrite == -1) { if (latestWrite == -1) {
Slog.w(TAG, "Failed to get storage hourly write"); Slog.w(TAG, "Failed to get storage write record");
return; return;
} }
updateStorageHourlyWrites(latestHourlyWrite); updateStorageWriteRecords(latestWrite);
int avgHourlyWrite = getAverageHourlyWrite(); int avgWriteAmount = getAverageWriteAmount();
Slog.i(TAG, "Set smart idle maintenance: " + "latest hourly write: " + Slog.i(TAG, "Set smart idle maintenance: " + "latest write amount: " +
latestHourlyWrite + ", average hourly write: " + avgHourlyWrite + latestWrite + ", average write amount: " + avgWriteAmount +
", min segment threshold: " + mMinSegmentsThreshold + ", min segment threshold: " + mMinSegmentsThreshold +
", dirty reclaim rate: " + mDirtyReclaimRate + ", dirty reclaim rate: " + mDirtyReclaimRate +
", segment reclaim weight:" + mSegmentReclaimWeight); ", segment reclaim weight: " + mSegmentReclaimWeight +
mVold.setGCUrgentPace(avgHourlyWrite, mMinSegmentsThreshold, mDirtyReclaimRate, ", period: " + sSmartIdleMaintPeriod);
mSegmentReclaimWeight); mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate,
mSegmentReclaimWeight, sSmartIdleMaintPeriod);
} else { } else {
Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress"); Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
} }