From 305ef9e1cffe02956b8f35fcbad155ce1baff8b6 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 21 Oct 2020 10:52:51 -0600 Subject: [PATCH] Migrate hot codepaths to formatSimple(). The recently added TextUtils.formatSimple() can efficiently format simple strings, roughly 6.5x faster than using String.format(). This change starts using this new method in hot codepaths identified from pprof traces, and this CL alone should reduce system_process CPU usage by 0.24%. Linked bug has detailed pprof screenshots. Bug: 170978902 Test: atest FrameworksCoreTests:android.text.TextUtilsTest Exempt-From-Owner-Approval: trivial refactoring Change-Id: Ie5a21a24be6dfcdb29768fe235e20f050fc111c7 --- .../android/service/notification/StatusBarNotification.java | 6 ++---- core/java/android/text/format/DateFormat.java | 3 ++- core/java/android/util/LocalLog.java | 5 ++--- core/java/com/android/internal/compat/ChangeReporter.java | 4 +++- core/tests/coretests/src/android/text/TextUtilsTest.java | 2 ++ .../core/java/com/android/server/am/BroadcastQueue.java | 3 ++- .../android/server/locksettings/LockSettingsStorage.java | 3 ++- .../java/com/android/server/notification/RankingHelper.java | 4 +++- 8 files changed, 18 insertions(+), 12 deletions(-) diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index 08d9905813902..579a8bfc9d993 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -16,7 +16,7 @@ package android.service.notification; -import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID; +import static android.text.TextUtils.formatSimple; import android.annotation.NonNull; import android.app.Notification; @@ -31,8 +31,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; -import android.provider.Settings; -import android.text.TextUtils; import com.android.internal.logging.InstanceId; import com.android.internal.logging.nano.MetricsProto; @@ -258,7 +256,7 @@ public class StatusBarNotification implements Parcelable { @Override public String toString() { - return String.format( + return formatSimple( "StatusBarNotification(pkg=%s user=%s id=%d tag=%s key=%s: %s)", this.pkg, this.user, this.id, this.tag, this.key, this.notification); diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index 4a0bec1300b7d..c2e3a80a5c517 100755 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -29,6 +29,7 @@ import android.provider.Settings; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.SpannedString; +import android.text.TextUtils; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -697,7 +698,7 @@ public class DateFormat { } private static String zeroPad(int inValue, int inMinDigits) { - return String.format(Locale.getDefault(), "%0" + inMinDigits + "d", inValue); + return TextUtils.formatSimple("%0" + inMinDigits + "d", inValue); } /** diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java index fda5e0d008e60..bf9a8384fe2c7 100644 --- a/core/java/android/util/LocalLog.java +++ b/core/java/android/util/LocalLog.java @@ -60,10 +60,9 @@ public final class LocalLog { } final String logLine; if (mUseLocalTimestamps) { - logLine = String.format("%s - %s", LocalDateTime.now(), msg); + logLine = LocalDateTime.now() + " - " + msg; } else { - logLine = String.format( - "%s / %s - %s", SystemClock.elapsedRealtime(), Instant.now(), msg); + logLine = SystemClock.elapsedRealtime() + " / " + Instant.now() + " - " + msg; } append(logLine); } diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java index 5e886a611913f..7a87be35ea983 100644 --- a/core/java/com/android/internal/compat/ChangeReporter.java +++ b/core/java/com/android/internal/compat/ChangeReporter.java @@ -16,6 +16,8 @@ package com.android.internal.compat; +import static android.text.TextUtils.formatSimple; + import android.annotation.IntDef; import android.util.Log; import android.util.Slog; @@ -175,7 +177,7 @@ public final class ChangeReporter { } private void debugLog(int uid, long changeId, int state) { - String message = String.format("Compat change id reported: %d; UID %d; state: %s", changeId, + String message = formatSimple("Compat change id reported: %d; UID %d; state: %s", changeId, uid, stateToString(state)); if (mSource == SOURCE_SYSTEM_SERVER) { Slog.d(TAG, message); diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java index 5362be337ede9..a0fc34923a4d4 100644 --- a/core/tests/coretests/src/android/text/TextUtilsTest.java +++ b/core/tests/coretests/src/android/text/TextUtilsTest.java @@ -853,6 +853,8 @@ public class TextUtilsTest { @Test public void testFormatSimple_Advanced() { + assertEquals("000000000000002a.ext", + formatSimple("%016x.%s", 42, "ext")); assertEquals("crtcl=0x002a:intrsv=Y:grnk=0x0018:gsmry=A:example:rnk=0x0000", formatSimple("crtcl=0x%04x:intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x", 42, 'Y', 24, 'A', "example", 0)); diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 57f811215e50c..f1c591522e519 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -18,6 +18,7 @@ package com.android.server.am; import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY; import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE; +import static android.text.TextUtils.formatSimple; import static com.android.server.am.ActivityManagerDebugConfig.*; @@ -1892,7 +1893,7 @@ public final class BroadcastQueue { } private String createBroadcastTraceTitle(BroadcastRecord record, int state) { - return String.format("Broadcast %s from %s (%s) %s", + return formatSimple("Broadcast %s from %s (%s) %s", state == BroadcastRecord.DELIVERY_PENDING ? "in queue" : "dispatched", record.callerPackage == null ? "" : record.callerPackage, record.callerApp == null ? "process unknown" : record.callerApp.toShortString(), diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java index 715e41c62a05a..5d0544b33cd7c 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java @@ -17,6 +17,7 @@ package com.android.server.locksettings; import static android.content.Context.USER_SERVICE; +import static android.text.TextUtils.formatSimple; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.internal.widget.LockPatternUtils.USER_FRP; @@ -527,7 +528,7 @@ class LockSettingsStorage { protected String getSynthenticPasswordStateFilePathForUser(int userId, long handle, String name) { final File baseDir = getSyntheticPasswordDirectoryForUser(userId); - final String baseName = String.format("%016x.%s", handle, name); + final String baseName = formatSimple("%016x.%s", handle, name); return new File(baseDir, baseName).getAbsolutePath(); } diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index b145e1eee3a3f..b4347e148ce01 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -15,6 +15,8 @@ */ package com.android.server.notification; +import static android.text.TextUtils.formatSimple; + import android.annotation.NonNull; import android.app.NotificationManager; import android.content.Context; @@ -138,7 +140,7 @@ public class RankingHelper { boolean isGroupSummary = record.getNotification().isGroupSummary(); record.setGlobalSortKey( - String.format("crtcl=0x%04x:intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x", + formatSimple("crtcl=0x%04x:intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x", record.getCriticality(), record.isRecentlyIntrusive() && record.getImportance() > NotificationManager.IMPORTANCE_MIN