Merge "Add Typeface memory perf test."
This commit is contained in:
committed by
Android (Google) Code Review
commit
d7afbefd40
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.android.perftests.core">
|
||||
|
||||
<permission android:name="com.android.perftests.core.TestPermission" />
|
||||
@@ -33,6 +34,17 @@
|
||||
android:exported="false"
|
||||
android:process=":some_provider" />
|
||||
|
||||
<!-- We remove EmojiCompat initializer here because it may crash the test process
|
||||
if the initializer runs while TypefaceSerializationPerfTest is running. -->
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
android:exported="false"
|
||||
tools:node="merge">
|
||||
<meta-data android:name="androidx.emoji2.text.EmojiCompatInitializer"
|
||||
tools:node="remove" />
|
||||
</provider>
|
||||
|
||||
<service
|
||||
android:name="android.view.autofill.MyAutofillService"
|
||||
android:label="PERF AutofillService"
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
package android.graphics.perftests;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Debug;
|
||||
import android.os.SharedMemory;
|
||||
import android.perftests.utils.BenchmarkState;
|
||||
import android.perftests.utils.PerfStatusReporter;
|
||||
import android.os.SystemClock;
|
||||
import android.perftests.utils.ManualBenchmarkState;
|
||||
import android.perftests.utils.PerfManualStatusReporter;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
@@ -37,16 +40,33 @@ import java.util.Map;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TypefaceSerializationPerfTest {
|
||||
|
||||
private static final String TAG = "TypefaceSerializationPerfTest";
|
||||
|
||||
@Rule
|
||||
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
|
||||
public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
|
||||
|
||||
@Test
|
||||
public void testSerializeFontMap() throws Exception {
|
||||
Map<String, Typeface> systemFontMap = Typeface.getSystemFontMap();
|
||||
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
|
||||
|
||||
while (state.keepRunning()) {
|
||||
long elapsedTime = 0;
|
||||
while (state.keepRunning(elapsedTime)) {
|
||||
long startTime = System.nanoTime();
|
||||
Typeface.serializeFontMap(systemFontMap);
|
||||
elapsedTime = System.nanoTime() - startTime;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializeFontMap_memory() throws Exception {
|
||||
Map<String, Typeface> systemFontMap = Typeface.getSystemFontMap();
|
||||
SharedMemory memory = Typeface.serializeFontMap(systemFontMap);
|
||||
ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
|
||||
|
||||
while (state.keepRunning(memory.getSize())) {
|
||||
// Rate-limiting
|
||||
SystemClock.sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,22 +74,54 @@ public class TypefaceSerializationPerfTest {
|
||||
public void testDeserializeFontMap() throws Exception {
|
||||
SharedMemory memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
|
||||
ByteBuffer buffer = memory.mapReadOnly().order(ByteOrder.BIG_ENDIAN);
|
||||
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
|
||||
|
||||
ArrayMap<String, Typeface> out = new ArrayMap<>();
|
||||
while (state.keepRunning()) {
|
||||
long elapsedTime = 0;
|
||||
while (state.keepRunning(elapsedTime)) {
|
||||
long startTime = System.nanoTime();
|
||||
buffer.position(0);
|
||||
Typeface.deserializeFontMap(buffer, out);
|
||||
elapsedTime = System.nanoTime() - startTime;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeFontMap_memory() throws Exception {
|
||||
SharedMemory memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
|
||||
ByteBuffer buffer = memory.mapReadOnly().order(ByteOrder.BIG_ENDIAN);
|
||||
ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
|
||||
|
||||
ArrayMap<String, Typeface> out = new ArrayMap<>();
|
||||
// Diff of native heap allocation size (in bytes) before and after deserializeFontMap.
|
||||
// Note: we don't measure memory usage of setSystemFontMap because setSystemFontMap sets
|
||||
// some global variables, and it's hard to clear them.
|
||||
long heapDiff = 0;
|
||||
// Sometimes heapDiff may become negative due to GC.
|
||||
// Use 0 in that case to avoid crashing in keepRunning.
|
||||
while (state.keepRunning(Math.max(0, heapDiff))) {
|
||||
buffer.position(0);
|
||||
long baselineSize = Debug.getNativeHeapAllocatedSize();
|
||||
Typeface.deserializeFontMap(buffer, out);
|
||||
long currentSize = Debug.getNativeHeapAllocatedSize();
|
||||
heapDiff = currentSize - baselineSize;
|
||||
Log.i(TAG, String.format("native heap alloc: current = %d, baseline = %d, diff = %d",
|
||||
currentSize, baselineSize, heapDiff));
|
||||
// Release native objects here to minimize the impact of GC.
|
||||
for (Typeface typeface : out.values()) {
|
||||
typeface.releaseNativeObjectForTest();
|
||||
}
|
||||
out.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSystemFontMap() throws Exception {
|
||||
SharedMemory memory = null;
|
||||
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
ManualBenchmarkState state = mPerfManualStatusReporter.getBenchmarkState();
|
||||
|
||||
while (state.keepRunning()) {
|
||||
state.pauseTiming();
|
||||
long elapsedTime = 0;
|
||||
while (state.keepRunning(elapsedTime)) {
|
||||
// Explicitly destroy lazy-loaded typefaces, so that we don't hit the mmap limit
|
||||
// (max_map_count).
|
||||
Typeface.destroySystemFontMap();
|
||||
@@ -78,8 +130,9 @@ public class TypefaceSerializationPerfTest {
|
||||
memory.close();
|
||||
}
|
||||
memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
|
||||
state.resumeTiming();
|
||||
long startTime = System.nanoTime();
|
||||
Typeface.setSystemFontMap(memory);
|
||||
elapsedTime = System.nanoTime() - startTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1176,6 +1176,17 @@ public class Typeface {
|
||||
mWeight = nativeGetWeight(ni);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the underlying native object.
|
||||
*
|
||||
* <p>For testing only. Do not use the instance after this method is called.
|
||||
* It is safe to call this method twice or more on the same instance.
|
||||
* @hide
|
||||
*/
|
||||
public void releaseNativeObjectForTest() {
|
||||
mCleaner.run();
|
||||
}
|
||||
|
||||
private static Typeface getSystemDefaultTypeface(@NonNull String familyName) {
|
||||
Typeface tf = sSystemFontMap.get(familyName);
|
||||
return tf == null ? Typeface.DEFAULT : tf;
|
||||
@@ -1425,7 +1436,7 @@ public class Typeface {
|
||||
public static void destroySystemFontMap() {
|
||||
synchronized (SYSTEM_FONT_MAP_LOCK) {
|
||||
for (Typeface typeface : sSystemFontMap.values()) {
|
||||
typeface.mCleaner.run();
|
||||
typeface.releaseNativeObjectForTest();
|
||||
}
|
||||
sSystemFontMap.clear();
|
||||
if (sSystemFontMapBuffer != null) {
|
||||
@@ -1433,9 +1444,25 @@ public class Typeface {
|
||||
}
|
||||
sSystemFontMapBuffer = null;
|
||||
sSystemFontMapSharedMemory = null;
|
||||
synchronized (sStyledCacheLock) {
|
||||
destroyTypefaceCacheLocked(sStyledTypefaceCache);
|
||||
}
|
||||
synchronized (sWeightCacheLock) {
|
||||
destroyTypefaceCacheLocked(sWeightTypefaceCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void destroyTypefaceCacheLocked(LongSparseArray<SparseArray<Typeface>> cache) {
|
||||
for (int i = 0; i < cache.size(); i++) {
|
||||
SparseArray<Typeface> array = cache.valueAt(i);
|
||||
for (int j = 0; j < array.size(); j++) {
|
||||
array.valueAt(j).releaseNativeObjectForTest();
|
||||
}
|
||||
}
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void loadPreinstalledSystemFontMap() {
|
||||
final FontConfig fontConfig = SystemFonts.getSystemPreinstalledFontConfig();
|
||||
|
||||
Reference in New Issue
Block a user