Merge "Make smart idle maint's period changable"
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user