Merge "Add LinearStdAllocator"
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 6f548bc..9fc3924 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -254,6 +254,7 @@
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
LOCAL_SRC_FILES += \
- microbench/DisplayListCanvasBench.cpp
+ microbench/DisplayListCanvasBench.cpp \
+ microbench/LinearAllocatorBench.cpp
include $(BUILD_EXECUTABLE)
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index 392bb3e..8f4ae3d 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -66,8 +66,7 @@
virtual ~DisplayListCanvas();
void reset(int width, int height);
-
- DisplayListData* finishRecording();
+ __attribute__((warn_unused_result)) DisplayListData* finishRecording();
// ----------------------------------------------------------------------------
// HWUI Canvas state operations
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index ed299e5..8f44ff0 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -41,7 +41,7 @@
virtual ~RecordingCanvas();
void reset(int width, int height);
- DisplayListData* finishRecording();
+ __attribute__((warn_unused_result)) DisplayListData* finishRecording();
// ----------------------------------------------------------------------------
// MISC HWUI OPERATIONS - TODO: CATEGORIZE
diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/microbench/DisplayListCanvasBench.cpp
index fd42adb..dccbe0b 100644
--- a/libs/hwui/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/microbench/DisplayListCanvasBench.cpp
@@ -15,7 +15,6 @@
*/
#include <benchmark/Benchmark.h>
-#include <utils/Singleton.h>
#include "DisplayList.h"
#if HWUI_NEW_OPS
@@ -59,13 +58,13 @@
BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_empty);
void BM_DisplayListCanvas_record_empty::Run(int iters) {
TestCanvas canvas(100, 100);
- canvas.finishRecording();
+ delete canvas.finishRecording();
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
canvas.reset(100, 100);
MicroBench::DoNotOptimize(&canvas);
- canvas.finishRecording();
+ delete canvas.finishRecording();
}
StopBenchmarkTiming();
}
@@ -73,7 +72,7 @@
BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_saverestore);
void BM_DisplayListCanvas_record_saverestore::Run(int iters) {
TestCanvas canvas(100, 100);
- canvas.finishRecording();
+ delete canvas.finishRecording();
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
@@ -83,7 +82,7 @@
MicroBench::DoNotOptimize(&canvas);
canvas.restore();
canvas.restore();
- canvas.finishRecording();
+ delete canvas.finishRecording();
}
StopBenchmarkTiming();
}
@@ -91,14 +90,14 @@
BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_translate);
void BM_DisplayListCanvas_record_translate::Run(int iters) {
TestCanvas canvas(100, 100);
- canvas.finishRecording();
+ delete canvas.finishRecording();
StartBenchmarkTiming();
for (int i = 0; i < iters; ++i) {
canvas.reset(100, 100);
canvas.scale(10, 10);
MicroBench::DoNotOptimize(&canvas);
- canvas.finishRecording();
+ delete canvas.finishRecording();
}
StopBenchmarkTiming();
}
diff --git a/libs/hwui/microbench/LinearAllocatorBench.cpp b/libs/hwui/microbench/LinearAllocatorBench.cpp
new file mode 100644
index 0000000..75f57cb
--- /dev/null
+++ b/libs/hwui/microbench/LinearAllocatorBench.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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 <benchmark/Benchmark.h>
+
+#include "utils/LinearAllocator.h"
+#include "microbench/MicroBench.h"
+
+#include <vector>
+
+using namespace android;
+using namespace android::uirenderer;
+
+BENCHMARK_NO_ARG(BM_LinearStdAllocator_vectorBaseline);
+void BM_LinearStdAllocator_vectorBaseline::Run(int iters) {
+ StartBenchmarkTiming();
+ for (int i = 0; i < iters; i++) {
+ std::vector<char> v;
+ for (int j = 0; j < 200; j++) {
+ v.push_back(j);
+ }
+ MicroBench::DoNotOptimize(&v);
+ }
+ StopBenchmarkTiming();
+}
+
+BENCHMARK_NO_ARG(BM_LinearStdAllocator_vector);
+void BM_LinearStdAllocator_vector::Run(int iters) {
+ StartBenchmarkTiming();
+ for (int i = 0; i < iters; i++) {
+ LinearAllocator la;
+ LinearStdAllocator<void*> stdAllocator(la);
+ std::vector<char, LinearStdAllocator<char> > v(stdAllocator);
+ for (int j = 0; j < 200; j++) {
+ v.push_back(j);
+ }
+ MicroBench::DoNotOptimize(&v);
+ }
+ StopBenchmarkTiming();
+}
diff --git a/libs/hwui/unit_tests/LinearAllocatorTests.cpp b/libs/hwui/unit_tests/LinearAllocatorTests.cpp
index b3959d1..02cd77a 100644
--- a/libs/hwui/unit_tests/LinearAllocatorTests.cpp
+++ b/libs/hwui/unit_tests/LinearAllocatorTests.cpp
@@ -106,3 +106,31 @@
// Checking for a double-destroy case
EXPECT_EQ(destroyed, false);
}
+
+TEST(LinearStdAllocator, simpleAllocate) {
+ LinearAllocator la;
+ LinearStdAllocator<void*> stdAllocator(la);
+
+ std::vector<char, LinearStdAllocator<char> > v(stdAllocator);
+ v.push_back(0);
+ char* initialLocation = &v[0];
+ v.push_back(10);
+ v.push_back(20);
+ v.push_back(30);
+
+ // expect to have allocated (since no space reserved), so [0] will have moved to
+ // slightly further down in the same LinearAllocator page
+ EXPECT_LT(initialLocation, &v[0]);
+ EXPECT_GT(initialLocation + 20, &v[0]);
+
+ // expect to have allocated again inserting 4 more entries
+ char* lastLocation = &v[0];
+ v.push_back(40);
+ v.push_back(50);
+ v.push_back(60);
+ v.push_back(70);
+
+ EXPECT_LT(lastLocation, &v[0]);
+ EXPECT_GT(lastLocation + 20, &v[0]);
+
+}
diff --git a/libs/hwui/utils/LinearAllocator.cpp b/libs/hwui/utils/LinearAllocator.cpp
index 0abe88b..e6a4c03 100644
--- a/libs/hwui/utils/LinearAllocator.cpp
+++ b/libs/hwui/utils/LinearAllocator.cpp
@@ -52,8 +52,8 @@
#define ALIGN_PTR(p) ((void*)(ALIGN((size_t)p)))
#if LOG_NDEBUG
-#define ADD_ALLOCATION(size)
-#define RM_ALLOCATION(size)
+#define ADD_ALLOCATION()
+#define RM_ALLOCATION()
#else
#include <utils/Thread.h>
#include <utils/Timers.h>
@@ -65,18 +65,18 @@
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (now > s_nextLog) {
s_nextLog = now + milliseconds_to_nanoseconds(10);
- ALOGV("Total memory usage: %zu kb", s_totalAllocations / 1024);
+ ALOGV("Total pages allocated: %zu", s_totalAllocations);
}
}
-static void _addAllocation(size_t size) {
+static void _addAllocation(int count) {
android::AutoMutex lock(s_mutex);
- s_totalAllocations += size;
+ s_totalAllocations += count;
_logUsageLocked();
}
-#define ADD_ALLOCATION(size) _addAllocation(size);
-#define RM_ALLOCATION(size) _addAllocation(-size);
+#define ADD_ALLOCATION(size) _addAllocation(1);
+#define RM_ALLOCATION(size) _addAllocation(-1);
#endif
#define min(x,y) (((x) < (y)) ? (x) : (y))
@@ -134,7 +134,7 @@
Page* next = p->next();
p->~Page();
free(p);
- RM_ALLOCATION(mPageSize);
+ RM_ALLOCATION();
p = next;
}
}
@@ -238,7 +238,7 @@
LinearAllocator::Page* LinearAllocator::newPage(size_t pageSize) {
pageSize = ALIGN(pageSize + sizeof(LinearAllocator::Page));
- ADD_ALLOCATION(pageSize);
+ ADD_ALLOCATION();
mTotalAllocated += pageSize;
mPageCount++;
void* buf = malloc(pageSize);
diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h
index d90dd82..ade4ab3 100644
--- a/libs/hwui/utils/LinearAllocator.h
+++ b/libs/hwui/utils/LinearAllocator.h
@@ -134,6 +134,47 @@
size_t mDedicatedPageCount;
};
+template <class T>
+class LinearStdAllocator {
+public:
+ typedef T value_type; // needed to implement std::allocator
+ typedef T* pointer; // needed to implement std::allocator
+
+ LinearStdAllocator(LinearAllocator& allocator)
+ : linearAllocator(allocator) {}
+ LinearStdAllocator(const LinearStdAllocator& other)
+ : linearAllocator(other.linearAllocator) {}
+ ~LinearStdAllocator() {}
+
+ // rebind marks that allocators can be rebound to different types
+ template <class U>
+ struct rebind {
+ typedef LinearStdAllocator<U> other;
+ };
+ // enable allocators to be constructed from other templated types
+ template <class U>
+ LinearStdAllocator(const LinearStdAllocator<U>& other)
+ : linearAllocator(other.linearAllocator) {}
+
+ T* allocate(size_t num, const void* = 0) {
+ return (T*)(linearAllocator.alloc(num * sizeof(T)));
+ }
+
+ void deallocate(pointer p, size_t num) {
+ // attempt to rewind, but no guarantees
+ linearAllocator.rewindIfLastAlloc(p, num * sizeof(T));
+ }
+
+ // public so template copy constructor can access
+ LinearAllocator& linearAllocator;
+};
+
+// return that all specializations of LinearStdAllocator are interchangeable
+template <class T1, class T2>
+bool operator== (const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) { return true; }
+template <class T1, class T2>
+bool operator!= (const LinearStdAllocator<T1>&, const LinearStdAllocator<T2>&) { return false; }
+
}; // namespace uirenderer
}; // namespace android