Merge "Add perf test for Typeface serialization."
This commit is contained in:
committed by
Android (Google) Code Review
commit
531245a7e9
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.graphics.perftests;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
import android.os.SharedMemory;
|
||||
import android.perftests.utils.BenchmarkState;
|
||||
import android.perftests.utils.PerfStatusReporter;
|
||||
|
||||
import androidx.test.filters.LargeTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Map;
|
||||
|
||||
@LargeTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TypefaceSerializationPerfTest {
|
||||
|
||||
@Rule
|
||||
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
|
||||
|
||||
@Test
|
||||
public void testSerializeFontMap() throws Exception {
|
||||
Map<String, Typeface> systemFontMap = Typeface.getSystemFontMap();
|
||||
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
|
||||
while (state.keepRunning()) {
|
||||
Typeface.serializeFontMap(systemFontMap);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeserializeFontMap() throws Exception {
|
||||
SharedMemory memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
|
||||
ByteBuffer buffer = memory.mapReadOnly().order(ByteOrder.BIG_ENDIAN);
|
||||
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
|
||||
while (state.keepRunning()) {
|
||||
buffer.position(0);
|
||||
Typeface.deserializeFontMap(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSystemFontMap() throws Exception {
|
||||
SharedMemory memory = null;
|
||||
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
|
||||
while (state.keepRunning()) {
|
||||
state.pauseTiming();
|
||||
// Explicitly destroy lazy-loaded typefaces, so that we don't hit the mmap limit
|
||||
// (max_map_count).
|
||||
Typeface.destroySystemFontMap();
|
||||
Typeface.loadPreinstalledSystemFontMap();
|
||||
if (memory != null) {
|
||||
memory.close();
|
||||
}
|
||||
memory = Typeface.serializeFontMap(Typeface.getSystemFontMap());
|
||||
state.resumeTiming();
|
||||
Typeface.setSystemFontMap(memory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,6 +169,8 @@ public class Typeface {
|
||||
@UnsupportedAppUsage
|
||||
public long native_instance;
|
||||
|
||||
private Runnable mCleaner;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(value = {NORMAL, BOLD, ITALIC, BOLD_ITALIC})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -1120,7 +1122,7 @@ public class Typeface {
|
||||
}
|
||||
|
||||
native_instance = ni;
|
||||
sRegistry.registerNativeAllocation(this, native_instance);
|
||||
mCleaner = sRegistry.registerNativeAllocation(this, native_instance);
|
||||
mStyle = nativeGetStyle(ni);
|
||||
mWeight = nativeGetWeight(ni);
|
||||
}
|
||||
@@ -1234,6 +1236,13 @@ public class Typeface {
|
||||
bos.write(value & 0xFF);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static Map<String, Typeface> getSystemFontMap() {
|
||||
synchronized (SYSTEM_FONT_MAP_LOCK) {
|
||||
return sSystemFontMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize font map and set it as system font map. This method should be called at most once
|
||||
* per process.
|
||||
@@ -1294,13 +1303,33 @@ public class Typeface {
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
/** @hide */
|
||||
@VisibleForTesting
|
||||
public static void destroySystemFontMap() {
|
||||
synchronized (SYSTEM_FONT_MAP_LOCK) {
|
||||
for (Typeface typeface : sSystemFontMap.values()) {
|
||||
typeface.mCleaner.run();
|
||||
}
|
||||
sSystemFontMap.clear();
|
||||
if (sSystemFontMapBuffer != null) {
|
||||
SharedMemory.unmap(sSystemFontMapBuffer);
|
||||
}
|
||||
sSystemFontMapBuffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static void loadPreinstalledSystemFontMap() {
|
||||
final HashMap<String, Typeface> systemFontMap = new HashMap<>();
|
||||
initSystemDefaultTypefaces(systemFontMap, SystemFonts.getRawSystemFallbackMap(),
|
||||
SystemFonts.getAliases());
|
||||
setSystemFontMap(systemFontMap);
|
||||
}
|
||||
|
||||
static {
|
||||
loadPreinstalledSystemFontMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -159,6 +159,13 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki
|
||||
return [fontPath, fontIndex, axesPtr, axesCount]() -> std::shared_ptr<minikin::MinikinFont> {
|
||||
std::string path(fontPath.data(), fontPath.size());
|
||||
sk_sp<SkData> data = SkData::MakeFromFileName(path.c_str());
|
||||
if (data == nullptr) {
|
||||
// This may happen if:
|
||||
// 1. When the process failed to open the file (e.g. invalid path or permission).
|
||||
// 2. When the process failed to map the file (e.g. hitting max_map_count limit).
|
||||
ALOGE("Failed to make SkData from file name: %s", path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
const void* fontPtr = data->data();
|
||||
size_t fontSize = data->size();
|
||||
std::vector<minikin::FontVariation> axes(axesPtr, axesPtr + axesCount);
|
||||
|
||||
Reference in New Issue
Block a user