Merge "Add some options to macrobench"
This commit is contained in:
@ -243,6 +243,7 @@ void JankTracker::dumpData(const ProfileData* data, int fd) {
|
||||
dprintf(fd, "\nTotal frames rendered: %u", data->totalFrameCount);
|
||||
dprintf(fd, "\nJanky frames: %u (%.2f%%)", data->jankFrameCount,
|
||||
(float) data->jankFrameCount / (float) data->totalFrameCount * 100.0f);
|
||||
dprintf(fd, "\n50th percentile: %ums", findPercentile(data, 50));
|
||||
dprintf(fd, "\n90th percentile: %ums", findPercentile(data, 90));
|
||||
dprintf(fd, "\n95th percentile: %ums", findPercentile(data, 95));
|
||||
dprintf(fd, "\n99th percentile: %ums", findPercentile(data, 99));
|
||||
|
@ -53,6 +53,8 @@ int Properties::overrideSpotShadowStrength = -1;
|
||||
ProfileType Properties::sProfileType = ProfileType::None;
|
||||
bool Properties::sDisableProfileBars = false;
|
||||
|
||||
bool Properties::waitForGpuCompletion = false;
|
||||
|
||||
static int property_get_int(const char* key, int defaultValue) {
|
||||
char buf[PROPERTY_VALUE_MAX] = {'\0',};
|
||||
|
||||
|
@ -285,6 +285,9 @@ public:
|
||||
|
||||
static ProfileType getProfileType();
|
||||
|
||||
// Should be used only by test apps
|
||||
static bool waitForGpuCompletion;
|
||||
|
||||
private:
|
||||
static ProfileType sProfileType;
|
||||
static bool sDisableProfileBars;
|
||||
|
@ -29,8 +29,6 @@
|
||||
|
||||
#define GLES_VERSION 2
|
||||
|
||||
#define WAIT_FOR_GPU_COMPLETION 0
|
||||
|
||||
// Android-specific addition that is used to show when frames began in systrace
|
||||
EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
|
||||
|
||||
@ -179,7 +177,10 @@ void EglManager::loadConfig() {
|
||||
}
|
||||
|
||||
void EglManager::createContext() {
|
||||
EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE };
|
||||
EGLint attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION,
|
||||
EGL_NONE
|
||||
};
|
||||
mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
|
||||
LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
|
||||
"Failed to create context, error = %s", egl_error_str());
|
||||
@ -318,12 +319,10 @@ void EglManager::damageFrame(const Frame& frame, const SkRect& dirty) {
|
||||
|
||||
bool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) {
|
||||
|
||||
#if WAIT_FOR_GPU_COMPLETION
|
||||
{
|
||||
if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
|
||||
ATRACE_NAME("Finishing GPU work");
|
||||
fence();
|
||||
}
|
||||
#endif
|
||||
|
||||
EGLint rects[4];
|
||||
frame.map(screenDirty, rects);
|
||||
|
@ -37,6 +37,7 @@ class TestScene {
|
||||
public:
|
||||
struct Options {
|
||||
int count = 0;
|
||||
int reportFrametimeWeight = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -38,6 +38,30 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class ModifiedMovingAverage {
|
||||
public:
|
||||
ModifiedMovingAverage(int weight) : mWeight(weight) {}
|
||||
|
||||
T add(T today) {
|
||||
if (!mHasValue) {
|
||||
mAverage = today;
|
||||
} else {
|
||||
mAverage = (((mWeight - 1) * mAverage) + today) / mWeight;
|
||||
}
|
||||
return mAverage;
|
||||
}
|
||||
|
||||
T average() {
|
||||
return mAverage;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mHasValue = false;
|
||||
int mWeight;
|
||||
T mAverage;
|
||||
};
|
||||
|
||||
void run(const TestScene::Info& info, const TestScene::Options& opts) {
|
||||
// Switch to the real display
|
||||
gDisplay = getBuiltInDisplay();
|
||||
@ -67,22 +91,35 @@ void run(const TestScene::Info& info, const TestScene::Options& opts) {
|
||||
proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
|
||||
|
||||
// Do a few cold runs then reset the stats so that the caches are all hot
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
testContext.waitForVsync();
|
||||
nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
|
||||
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
|
||||
proxy->syncAndDrawFrame();
|
||||
}
|
||||
|
||||
proxy->resetProfileInfo();
|
||||
proxy->fence();
|
||||
|
||||
ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
|
||||
|
||||
for (int i = 0; i < opts.count; i++) {
|
||||
testContext.waitForVsync();
|
||||
|
||||
ATRACE_NAME("UI-Draw Frame");
|
||||
nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
|
||||
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
|
||||
scene->doFrame(i);
|
||||
proxy->syncAndDrawFrame();
|
||||
{
|
||||
ATRACE_NAME("UI-Draw Frame");
|
||||
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
|
||||
scene->doFrame(i);
|
||||
proxy->syncAndDrawFrame();
|
||||
}
|
||||
proxy->fence();
|
||||
nsecs_t done = systemTime(CLOCK_MONOTONIC);
|
||||
if (opts.reportFrametimeWeight) {
|
||||
avgMs.add((done - vsync) / 1000000.0);
|
||||
if (i % 10 == 9) {
|
||||
printf("Average frametime %.3fms\n", avgMs.average());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proxy->dumpProfileInfo(STDOUT_FILENO, 0);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "tests/common/TestScene.h"
|
||||
|
||||
#include "protos/hwui.pb.h"
|
||||
#include "Properties.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
@ -25,26 +26,38 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
using namespace android;
|
||||
using namespace android::uirenderer;
|
||||
using namespace android::uirenderer::test;
|
||||
|
||||
static int gFrameCount = 150;
|
||||
static int gRepeatCount = 1;
|
||||
static std::vector<TestScene::Info> gRunTests;
|
||||
static TestScene::Options gOpts;
|
||||
|
||||
void run(const TestScene::Info& info, const TestScene::Options& opts);
|
||||
|
||||
static void printHelp() {
|
||||
printf("\
|
||||
USAGE: hwuitest [OPTIONS] <TESTNAME>\n\
|
||||
\n\
|
||||
OPTIONS:\n\
|
||||
-c, --count=NUM NUM loops a test should run (example, number of frames)\n\
|
||||
-r, --runs=NUM Repeat the test(s) NUM times\n\
|
||||
-h, --help Display this help\n\
|
||||
--list List all tests\n\
|
||||
\n");
|
||||
printf(R"(
|
||||
USAGE: hwuitest [OPTIONS] <TESTNAME>
|
||||
|
||||
OPTIONS:
|
||||
-c, --count=NUM NUM loops a test should run (example, number of frames)
|
||||
-r, --runs=NUM Repeat the test(s) NUM times
|
||||
-h, --help Display this help
|
||||
--list List all tests
|
||||
--wait-for-gpu Set this to wait for the GPU before producing the
|
||||
next frame. Note that without locked clocks this will
|
||||
pathologically bad performance due to large idle time
|
||||
--report-frametime[=weight] If set, the test will print to stdout the
|
||||
moving average frametime. Weight is optional, default is 10
|
||||
--cpuset=name Adds the test to the specified cpuset before running
|
||||
Not supported on all devices and needs root
|
||||
)");
|
||||
}
|
||||
|
||||
static void listTests() {
|
||||
@ -77,11 +90,56 @@ static void listTests() {
|
||||
}
|
||||
}
|
||||
|
||||
static void moveToCpuSet(const char* cpusetName) {
|
||||
if (access("/dev/cpuset/tasks", F_OK)) {
|
||||
fprintf(stderr, "don't have access to cpusets, skipping...\n");
|
||||
return;
|
||||
}
|
||||
static const int BUF_SIZE = 100;
|
||||
char buffer[BUF_SIZE];
|
||||
|
||||
if (snprintf(buffer, BUF_SIZE, "/dev/cpuset/%s/tasks", cpusetName) >= BUF_SIZE) {
|
||||
fprintf(stderr, "Error, cpusetName too large to fit in buffer '%s'\n", cpusetName);
|
||||
return;
|
||||
}
|
||||
int fd = open(buffer, O_WRONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Error opening file %d\n", errno);
|
||||
return;
|
||||
}
|
||||
pid_t pid = getpid();
|
||||
|
||||
int towrite = snprintf(buffer, BUF_SIZE, "%ld", (long) pid);
|
||||
if (towrite >= BUF_SIZE) {
|
||||
fprintf(stderr, "Buffer wasn't large enough?\n");
|
||||
} else {
|
||||
if (write(fd, buffer, towrite) != towrite) {
|
||||
fprintf(stderr, "Failed to write, errno=%d", errno);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
// For options that only exist in long-form. Anything in the
|
||||
// 0-255 range is reserved for short options (which just use their ASCII value)
|
||||
namespace LongOpts {
|
||||
enum {
|
||||
Reserved = 255,
|
||||
List,
|
||||
WaitForGpu,
|
||||
ReportFrametime,
|
||||
CpuSet,
|
||||
};
|
||||
}
|
||||
|
||||
static const struct option LONG_OPTIONS[] = {
|
||||
{ "frames", required_argument, nullptr, 'f' },
|
||||
{ "repeat", required_argument, nullptr, 'r' },
|
||||
{ "help", no_argument, nullptr, 'h' },
|
||||
{ "list", no_argument, nullptr, 'l' },
|
||||
{ "list", no_argument, nullptr, LongOpts::List },
|
||||
{ "wait-for-gpu", no_argument, nullptr, LongOpts::WaitForGpu },
|
||||
{ "report-frametime", optional_argument, nullptr, LongOpts::ReportFrametime },
|
||||
{ "cpuset", required_argument, nullptr, LongOpts::CpuSet },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@ -89,8 +147,6 @@ static const char* SHORT_OPTIONS = "c:r:h";
|
||||
|
||||
void parseOptions(int argc, char* argv[]) {
|
||||
int c;
|
||||
// temporary variable
|
||||
int count;
|
||||
bool error = false;
|
||||
opterr = 0;
|
||||
|
||||
@ -110,31 +166,53 @@ void parseOptions(int argc, char* argv[]) {
|
||||
// (although none of the current LONG_OPTIONS do this...)
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case LongOpts::List:
|
||||
listTests();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
count = atoi(optarg);
|
||||
if (!count) {
|
||||
gOpts.count = atoi(optarg);
|
||||
if (!gOpts.count) {
|
||||
fprintf(stderr, "Invalid frames argument '%s'\n", optarg);
|
||||
error = true;
|
||||
} else {
|
||||
gFrameCount = (count > 0 ? count : INT_MAX);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
count = atoi(optarg);
|
||||
if (!count) {
|
||||
gRepeatCount = atoi(optarg);
|
||||
if (!gRepeatCount) {
|
||||
fprintf(stderr, "Invalid repeat argument '%s'\n", optarg);
|
||||
error = true;
|
||||
} else {
|
||||
gRepeatCount = (count > 0 ? count : INT_MAX);
|
||||
gRepeatCount = (gRepeatCount > 0 ? gRepeatCount : INT_MAX);
|
||||
}
|
||||
break;
|
||||
|
||||
case LongOpts::ReportFrametime:
|
||||
if (optarg) {
|
||||
gOpts.reportFrametimeWeight = atoi(optarg);
|
||||
if (!gOpts.reportFrametimeWeight) {
|
||||
fprintf(stderr, "Invalid report frametime weight '%s'\n", optarg);
|
||||
error = true;
|
||||
}
|
||||
} else {
|
||||
gOpts.reportFrametimeWeight = 10;
|
||||
}
|
||||
break;
|
||||
|
||||
case LongOpts::WaitForGpu:
|
||||
Properties::waitForGpuCompletion = true;
|
||||
break;
|
||||
|
||||
case LongOpts::CpuSet:
|
||||
if (!optarg) {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
moveToCpuSet(optarg);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
printHelp();
|
||||
exit(EXIT_SUCCESS);
|
||||
@ -172,13 +250,14 @@ void parseOptions(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// set defaults
|
||||
gOpts.count = 150;
|
||||
|
||||
parseOptions(argc, argv);
|
||||
|
||||
TestScene::Options opts;
|
||||
opts.count = gFrameCount;
|
||||
for (int i = 0; i < gRepeatCount; i++) {
|
||||
for (auto&& test : gRunTests) {
|
||||
run(test, opts);
|
||||
run(test, gOpts);
|
||||
}
|
||||
}
|
||||
printf("Success!\n");
|
||||
|
54
libs/hwui/tests/scripts/prep_volantis.sh
Executable file
54
libs/hwui/tests/scripts/prep_volantis.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
adb root
|
||||
adb wait-for-device
|
||||
adb shell stop mpdecision
|
||||
adb shell stop perfd
|
||||
adb shell stop
|
||||
for pid in $( adb shell ps | awk '{ if ( $9 == "surfaceflinger" ) { print $2 } }' ); do
|
||||
adb shell kill $pid
|
||||
done
|
||||
adb shell setprop debug.egl.traceGpuCompletion 1
|
||||
adb shell daemonize surfaceflinger
|
||||
sleep 3
|
||||
adb shell setprop service.bootanim.exit 1
|
||||
|
||||
# cpu possible frequencies
|
||||
# 204000 229500 255000 280500 306000 331500 357000 382500 408000 433500 459000
|
||||
# 484500 510000 535500 561000 586500 612000 637500 663000 688500 714000 739500
|
||||
# 765000 790500 816000 841500 867000 892500 918000 943500 969000 994500 1020000
|
||||
# 1122000 1224000 1326000 1428000 1530000 1632000 1734000 1836000 1938000
|
||||
# 2014500 2091000 2193000 2295000 2397000 2499000
|
||||
|
||||
S=1326000
|
||||
echo "set cpu $cpu to $S hz";
|
||||
adb shell "echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
|
||||
adb shell "echo $S > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"
|
||||
adb shell "echo $S > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"
|
||||
adb shell "echo $S > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
|
||||
|
||||
#disable hotplug
|
||||
adb shell "echo 0 > /sys/devices/system/cpu/cpuquiet/tegra_cpuquiet/enable"
|
||||
|
||||
# gbus possible rates
|
||||
# 72000 108000 180000 252000 324000 396000 468000 540000 612000 648000
|
||||
# 684000 708000 756000 804000 852000 (kHz)
|
||||
|
||||
S=324000000
|
||||
echo "set gpu to $s hz"
|
||||
adb shell "echo 1 > /d/clock/override.gbus/state"
|
||||
adb shell "echo $S > /d/clock/override.gbus/rate"
|
Reference in New Issue
Block a user