From a8a58ffdeeb6a4a05de227a34972d99c005d2bf0 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Wed, 18 May 2016 11:58:39 -0700 Subject: [PATCH] Frameworks/base: Optimize LoadedApk Preallocate storage lists and avoid TextUtils and its string builder for a common code path. Optimize list join helper to not have a check in the loop. Bug: 28801010 Change-Id: Iafc582031f973d718252b34bcda6405a77425628 --- core/java/android/app/LoadedApk.java | 15 ++++++++++++--- core/java/android/text/TextUtils.java | 11 +++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 3f870005abfe4..10566342325f0 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -458,8 +458,14 @@ public final class LoadedApk { } } - final List zipPaths = new ArrayList<>(); - final List libPaths = new ArrayList<>(); + // Lists for the elements of zip/code and native libraries. + // + // Both lists are usually not empty. We expect on average one APK for the zip component, + // but shared libraries and splits are not uncommon. We expect at least three elements + // for native libraries (app-based, system, vendor). As such, give both some breathing + // space and initialize to a small value (instead of incurring growth code). + final List zipPaths = new ArrayList<>(10); + final List libPaths = new ArrayList<>(10); makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths); final boolean isBundledApp = mApplicationInfo.isSystemApp() @@ -495,8 +501,11 @@ public final class LoadedApk { /* * With all the combination done (if necessary, actually create the java class * loader and set up JIT profiling support if necessary. + * + * In many cases this is a single APK, so try to avoid the StringBuilder in TextUtils. */ - final String zip = TextUtils.join(File.pathSeparator, zipPaths); + final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : + TextUtils.join(File.pathSeparator, zipPaths); if (ActivityThread.localLOGV) Slog.v(ActivityThread.TAG, "Class path: " + zip + diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 71b53f1f42ae2..1c13962c7dfda 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -309,14 +309,13 @@ public class TextUtils { */ public static String join(CharSequence delimiter, Iterable tokens) { StringBuilder sb = new StringBuilder(); - boolean firstTime = true; - for (Object token: tokens) { - if (firstTime) { - firstTime = false; - } else { + Iterator it = tokens.iterator(); + if (it.hasNext()) { + sb.append(it.next()); + while (it.hasNext()) { sb.append(delimiter); + sb.append(it.next()); } - sb.append(token); } return sb.toString(); }