From 9d07c41b4d35a22e8974efc3b7776eeb0a01733a Mon Sep 17 00:00:00 2001 From: Alex Buynytskyy Date: Wed, 18 Aug 2021 10:53:45 -0700 Subject: [PATCH] Slightly more efficient job storage. Use binary XML: - less space on disk: 500 jobs file size 99093b vs 177982b - slightly better reading times: see perf test, - less memory usage: 2.7M (https://pprof.corp.google.com/?id=ab851a8e29fa10e4e31635d9b7219be5&tab=tree&focus=writeJobsMapImpl) vs 130K (https://pprof.corp.google.com/?id=41244f6c3fa65f54b930087939a28231&tab=tree&focus=writeJobsMapImpl). BEFORE: [1/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobReading_fewJobs_badRTC: PASSED (20.018s) testPersistedJobReading_fewJobs_badRTC_mean: 4403782 testPersistedJobReading_fewJobs_badRTC_mean: 4329086 testPersistedJobReading_fewJobs_badRTC_mean: 4361577 [2/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobWriting_manyJobs: PASSED (20.894s) testPersistedJobWriting_manyJobs_mean: 33269431 testPersistedJobWriting_manyJobs_mean: 32886187 testPersistedJobWriting_manyJobs_mean: 33093695 [3/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobReading_manyJobs_goodRTC: PASSED (20.822s) testPersistedJobReading_manyJobs_goodRTC_mean: 39305058 testPersistedJobReading_manyJobs_goodRTC_mean: 38768541 testPersistedJobReading_manyJobs_goodRTC_mean: 38944530 [4/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobWriting_fewJobs: PASSED (21.046s) testPersistedJobWriting_fewJobs_mean: 4301181 testPersistedJobWriting_fewJobs_mean: 4164938 testPersistedJobWriting_fewJobs_mean: 4146446 [5/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobReading_fewJobs_goodRTC: PASSED (21.137s) testPersistedJobReading_fewJobs_goodRTC_mean: 4230574 testPersistedJobReading_fewJobs_goodRTC_mean: 4184341 testPersistedJobReading_fewJobs_goodRTC_mean: 4192015 [6/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobReading_manyJobs_badRTC: PASSED (21.016s) testPersistedJobReading_manyJobs_badRTC_mean: 39166861 testPersistedJobReading_manyJobs_badRTC_mean: 39049685 testPersistedJobReading_manyJobs_badRTC_mean: 38929124 AFTER: [1/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobReading_fewJobs_badRTC: PASSED (19.525s) testPersistedJobReading_fewJobs_badRTC_mean: 4082319 testPersistedJobReading_fewJobs_badRTC_mean: 4067636 testPersistedJobReading_fewJobs_badRTC_mean: 4066729 [2/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobWriting_manyJobs: PASSED (20.965s) testPersistedJobWriting_manyJobs_mean: 32787281 testPersistedJobWriting_manyJobs_mean: 32545741 testPersistedJobWriting_manyJobs_mean: 33066635 [3/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobReading_manyJobs_goodRTC: PASSED (20.917s) testPersistedJobReading_manyJobs_goodRTC_mean: 36971876 testPersistedJobReading_manyJobs_goodRTC_mean: 36671859 testPersistedJobReading_manyJobs_goodRTC_mean: 37033008 [4/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobWriting_fewJobs: PASSED (21.171s) testPersistedJobWriting_fewJobs_mean: 4271303 testPersistedJobWriting_fewJobs_mean: 4205693 testPersistedJobWriting_fewJobs_mean: 4135812 [5/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobReading_fewJobs_goodRTC: PASSED (20.992s) testPersistedJobReading_fewJobs_goodRTC_mean: 3914909 testPersistedJobReading_fewJobs_goodRTC_mean: 3897198 testPersistedJobReading_fewJobs_goodRTC_mean: 3932903 [6/6] com.android.frameworks.perftests.job.JobStorePerfTests#testPersistedJobReading_manyJobs_badRTC: PASSED (20.995s) testPersistedJobReading_manyJobs_badRTC_mean: 37105827 testPersistedJobReading_manyJobs_badRTC_mean: 36804174 testPersistedJobReading_manyJobs_badRTC_mean: 36943056 Bug: 135200955 Fixes: 135200955 Test: atest CtsJobSchedulerTestCases JobStoreTest JobStorePerfTests Change-Id: I611c6fb8df029050a7e3ee300547152016a08f5c --- .../java/com/android/server/job/JobStore.java | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java index 7a2840709d15f..a660dec72495e 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java @@ -41,13 +41,13 @@ import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SystemConfigFileCommitEventLogger; +import android.util.TypedXmlSerializer; import android.util.Xml; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; -import com.android.internal.util.FastXmlSerializer; import com.android.server.IoThread; import com.android.server.LocalServices; import com.android.server.job.JobSchedulerInternal.JobStorePersistStats; @@ -57,13 +57,12 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -469,11 +468,9 @@ public final class JobStore { int numJobs = 0; int numSystemJobs = 0; int numSyncJobs = 0; - try { - mEventLogger.setStartTime(SystemClock.uptimeMillis()); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - XmlSerializer out = new FastXmlSerializer(); - out.setOutput(baos, StandardCharsets.UTF_8.name()); + mEventLogger.setStartTime(SystemClock.uptimeMillis()); + try (FileOutputStream fos = mJobsFile.startWrite()) { + TypedXmlSerializer out = Xml.resolveSerializer(fos); out.startDocument(null, true); out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); @@ -502,9 +499,6 @@ public final class JobStore { out.endTag(null, "job-info"); out.endDocument(); - // Write out to disk in one fell swoop. - FileOutputStream fos = mJobsFile.startWrite(); - fos.write(baos.toByteArray()); mJobsFile.finishWrite(fos); } catch (IOException e) { if (DEBUG) { @@ -703,9 +697,8 @@ public final class JobStore { int numJobs = 0; int numSystemJobs = 0; int numSyncJobs = 0; - try { - List jobs; - FileInputStream fis = mJobsFile.openRead(); + List jobs; + try (FileInputStream fis = mJobsFile.openRead()) { synchronized (mLock) { jobs = readJobMapImpl(fis, rtcGood); if (jobs != null) { @@ -726,7 +719,6 @@ public final class JobStore { } } } - fis.close(); } catch (FileNotFoundException e) { if (DEBUG) { Slog.d(TAG, "Could not find jobs file, probably there was nothing to load."); @@ -743,10 +735,9 @@ public final class JobStore { Slog.i(TAG, "Read " + numJobs + " jobs"); } - private List readJobMapImpl(FileInputStream fis, boolean rtcIsGood) + private List readJobMapImpl(InputStream fis, boolean rtcIsGood) throws XmlPullParserException, IOException { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, StandardCharsets.UTF_8.name()); + XmlPullParser parser = Xml.resolvePullParser(fis); int eventType = parser.getEventType(); while (eventType != XmlPullParser.START_TAG &&