From 4a4bc892e826849bd58606d99408f1bfbceddc3b Mon Sep 17 00:00:00 2001 From: John Reck Date: Mon, 12 Oct 2015 07:38:22 -0700 Subject: [PATCH] Microbench hackery Change-Id: I35428350e16982824bb4e8a0015a4cb98b1c0799 --- libs/hwui/Android.mk | 24 +++ libs/hwui/DisplayList.cpp | 14 +- .../microbench/DisplayListCanvasBench.cpp | 146 ++++++++++++++++++ libs/hwui/microbench/MicroBench.h | 35 +++++ 4 files changed, 213 insertions(+), 6 deletions(-) create mode 100644 libs/hwui/microbench/DisplayListCanvasBench.cpp create mode 100644 libs/hwui/microbench/MicroBench.h diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index eaade34a1db63..8011b5945ee21 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -213,3 +213,27 @@ LOCAL_SRC_FILES += \ tests/main.cpp include $(BUILD_EXECUTABLE) + +# ------------------------ +# Micro-bench app +# --------------------- +include $(CLEAR_VARS) + +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp +LOCAL_MODULE:= hwuimicro +LOCAL_MODULE_TAGS := tests +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_MULTILIB := both +LOCAL_MODULE_STEM_32 := hwuimicro +LOCAL_MODULE_STEM_64 := hwuimicro64 +LOCAL_SHARED_LIBRARIES := $(hwui_shared_libraries) +LOCAL_CFLAGS := $(hwui_cflags) +LOCAL_C_INCLUDES += bionic/benchmarks/ + +LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static +LOCAL_STATIC_LIBRARIES := libbenchmark libbase + +LOCAL_SRC_FILES += \ + microbench/DisplayListCanvasBench.cpp + +include $(BUILD_EXECUTABLE) diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index 0af9420533eba..ee51da2fb1160 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -36,15 +36,17 @@ DisplayListData::~DisplayListData() { } void DisplayListData::cleanupResources() { - ResourceCache& resourceCache = ResourceCache::getInstance(); - resourceCache.lock(); + if (CC_UNLIKELY(patchResources.size())) { + ResourceCache& resourceCache = ResourceCache::getInstance(); + resourceCache.lock(); - for (size_t i = 0; i < patchResources.size(); i++) { - resourceCache.decrementRefcountLocked(patchResources[i]); + for (size_t i = 0; i < patchResources.size(); i++) { + resourceCache.decrementRefcountLocked(patchResources[i]); + } + + resourceCache.unlock(); } - resourceCache.unlock(); - for (size_t i = 0; i < pathResources.size(); i++) { const SkPath* path = pathResources[i]; if (path->unique() && Caches::hasInstance()) { diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/microbench/DisplayListCanvasBench.cpp new file mode 100644 index 0000000000000..7b6be7a17a37d --- /dev/null +++ b/libs/hwui/microbench/DisplayListCanvasBench.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2015 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. + */ + +#include +#include + +#include "DisplayList.h" +#include "DisplayListCanvas.h" +#include "microbench/MicroBench.h" + +using namespace android; +using namespace android::uirenderer; + +BENCHMARK_NO_ARG(BM_DisplayListData_alloc); +void BM_DisplayListData_alloc::Run(int iters) { + StartBenchmarkTiming(); + for (int i = 0; i < iters; ++i) { + auto data = new DisplayListData(); + MicroBench::DoNotOptimize(data); + delete data; + } + StopBenchmarkTiming(); +} + +BENCHMARK_NO_ARG(BM_DisplayListData_alloc_theoretical); +void BM_DisplayListData_alloc_theoretical::Run(int iters) { + StartBenchmarkTiming(); + for (int i = 0; i < iters; ++i) { + auto data = new char[sizeof(DisplayListData)]; + MicroBench::DoNotOptimize(data); + delete[] data; + } + StopBenchmarkTiming(); +} + +BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_empty); +void BM_DisplayListCanvas_record_empty::Run(int iters) { + DisplayListCanvas canvas(100, 100); + canvas.finishRecording(); + + StartBenchmarkTiming(); + for (int i = 0; i < iters; ++i) { + canvas.reset(100, 100); + MicroBench::DoNotOptimize(&canvas); + canvas.finishRecording(); + } + StopBenchmarkTiming(); +} + +BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_saverestore); +void BM_DisplayListCanvas_record_saverestore::Run(int iters) { + DisplayListCanvas canvas(100, 100); + canvas.finishRecording(); + + StartBenchmarkTiming(); + for (int i = 0; i < iters; ++i) { + canvas.reset(100, 100); + canvas.save(SkCanvas::kMatrixClip_SaveFlag); + canvas.save(SkCanvas::kMatrixClip_SaveFlag); + MicroBench::DoNotOptimize(&canvas); + canvas.restore(); + canvas.restore(); + canvas.finishRecording(); + } + StopBenchmarkTiming(); +} + +BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_translate); +void BM_DisplayListCanvas_record_translate::Run(int iters) { + DisplayListCanvas canvas(100, 100); + canvas.finishRecording(); + + StartBenchmarkTiming(); + for (int i = 0; i < iters; ++i) { + canvas.reset(100, 100); + canvas.scale(10, 10); + MicroBench::DoNotOptimize(&canvas); + canvas.finishRecording(); + } + StopBenchmarkTiming(); +} + +class NullClient: public CanvasStateClient { + void onViewportInitialized() override {} + void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {} + GLuint getTargetFbo() const override { return 0; } +}; + +BENCHMARK_NO_ARG(BM_CanvasState_saverestore); +void BM_CanvasState_saverestore::Run(int iters) { + NullClient client; + CanvasState state(client); + state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3()); + + StartBenchmarkTiming(); + for (int i = 0; i < iters; ++i) { + state.save(SkCanvas::kMatrixClip_SaveFlag); + state.save(SkCanvas::kMatrixClip_SaveFlag); + MicroBench::DoNotOptimize(&state); + state.restore(); + state.restore(); + } + StopBenchmarkTiming(); +} + +BENCHMARK_NO_ARG(BM_CanvasState_init); +void BM_CanvasState_init::Run(int iters) { + NullClient client; + CanvasState state(client); + state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3()); + + StartBenchmarkTiming(); + for (int i = 0; i < iters; ++i) { + state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3()); + MicroBench::DoNotOptimize(&state); + } + StopBenchmarkTiming(); +} + +BENCHMARK_NO_ARG(BM_CanvasState_translate); +void BM_CanvasState_translate::Run(int iters) { + NullClient client; + CanvasState state(client); + state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3()); + + StartBenchmarkTiming(); + for (int i = 0; i < iters; ++i) { + state.translate(5, 5, 0); + MicroBench::DoNotOptimize(&state); + state.translate(-5, -5, 0); + } + StopBenchmarkTiming(); +} diff --git a/libs/hwui/microbench/MicroBench.h b/libs/hwui/microbench/MicroBench.h new file mode 100644 index 0000000000000..f05e92cd86d15 --- /dev/null +++ b/libs/hwui/microbench/MicroBench.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 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. + */ +#ifndef MICROBENCH_MICROBENCH_H +#define MICROBENCH_MICROBENCH_H + +namespace android { +namespace uirenderer { + +#define NO_INLINE __attribute__ ((noinline)) + +class MicroBench { +public: + template + static inline void DoNotOptimize(Tp const& value) { + asm volatile("" : "+rm" (const_cast(value))); + } +}; + +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* MICROBENCH_MICROBENCH_H */