Working on an automated performance test

This commit is contained in:
Brad Davis 2016-04-05 13:25:00 -07:00
parent 4b7a4e80ff
commit f3e5306f90
8 changed files with 324 additions and 4 deletions

View file

@ -0,0 +1,11 @@
var qml = Script.resolvePath('playaPerformanceTest.qml');
qmlWindow = new OverlayWindow({
title: 'Test Qml',
source: qml,
height: 320,
width: 640,
toolWindow: false,
visible: true
});

View file

@ -0,0 +1,193 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
Rectangle {
id: root
width: parent ? parent.width : 100
height: parent ? parent.height : 100
signal sendToScript(var message);
property var values: [];
property var host: AddressManager.hostname
Component.onCompleted: {
Window.domainChanged.connect(function(newDomain){
if (newDomain !== root.host) {
root.host = AddressManager.hostname;
}
});
}
onHostChanged: {
if (root.running) {
if (host !== "Dreaming" && host !== "Playa") {
return;
}
console.log("PERF new domain " + host)
if (host === "Dreaming") {
AddressManager.handleLookupString("Playa");
return;
}
if (host === "Playa") {
console.log("PERF starting timers and frame timing");
// If we've arrived, start running the test
FrameTimings.start();
rotationTimer.start();
stopTimer.start();
}
}
}
function startTest() {
console.log("PERF startTest()");
root.running = true
console.log("PERF current host: " + AddressManager.hostname)
// If we're already in playa, we need to go somewhere else...
if ("Playa" === AddressManager.hostname) {
console.log("PERF Navigating to dreaming")
AddressManager.handleLookupString("Dreaming/0,0,0");
} else {
console.log("PERF Navigating to playa")
AddressManager.handleLookupString("Playa");
}
}
function stopTest() {
console.log("PERF stopTest()");
root.running = false;
stopTimer.stop();
rotationTimer.stop();
FrameTimings.finish();
root.values = FrameTimings.getValues();
AddressManager.handleLookupString("Dreaming/0,0,0");
resultGraph.requestPaint();
console.log("PERF Value Count: " + root.values.length);
console.log("PERF Max: " + FrameTimings.max);
console.log("PERF Min: " + FrameTimings.min);
console.log("PERF Avg: " + FrameTimings.mean);
console.log("PERF StdDev: " + FrameTimings.standardDeviation);
}
function yaw(a) {
var y = -Math.sin( a / 2.0 );
var w = Math.cos( a / 2.0 );
var l = Math.sqrt((y * y) + (w * w));
return Qt.quaternion(w / l, 0, y / l, 0);
}
function rotate() {
MyAvatar.setOrientationVar(yaw(Date.now() / 1000));
}
property bool running: false
Timer {
id: stopTimer
interval: 30 * 1000
repeat: false
running: false
onTriggered: stopTest();
}
Timer {
id: rotationTimer
interval: 100
repeat: true
running: false
onTriggered: rotate();
}
Row {
id: row
anchors { left: parent.left; right: parent.right; }
spacing: 8
Button {
text: root.running ? "Stop" : "Run"
onClicked: root.running ? stopTest() : startTest();
}
}
// Rectangle {
// anchors { left: parent.left; right: parent.right; top: row.bottom; topMargin: 8; bottom: parent.bottom; }
// //anchors.fill: parent
// color: "#7fff0000"
// }
// Return the maximum value from a set of values
function vv(i, max) {
var perValue = values.length / max;
var start = Math.floor(perValue * i);
var end = Math.min(values.length, Math.floor(start + perValue));
var result = 0;
for (var j = start; j <= end; ++j) {
result = Math.max(result, values[j]);
}
return result;
}
Canvas {
id: resultGraph
anchors { left: parent.left; right: parent.right; top: row.bottom; margins: 16; bottom: parent.bottom; }
property real maxValue: 200;
property real perFrame: 10000;
property real k1: (5 / maxValue) * height;
property real k2: (10 / maxValue) * height;
property real k3: (100 / maxValue) * height;
onPaint: {
var ctx = getContext("2d");
if (values.length === 0) {
ctx.fillStyle = Qt.rgba(1, 0, 0, 1);
ctx.fillRect(0, 0, width, height);
return;
}
//ctx.setTransform(1, 0, 0, -1, 0, 0);
ctx.fillStyle = Qt.rgba(0, 0, 0, 1);
ctx.fillRect(0, 0, width, height);
ctx.strokeStyle= "gray";
ctx.lineWidth="1";
ctx.beginPath();
for (var i = 0; i < width; ++i) {
var value = vv(i, width); //values[Math.min(i, values.length - 1)];
value /= 10000;
value /= maxValue;
ctx.moveTo(i, height);
ctx.lineTo(i, height - (height * value));
}
ctx.stroke();
ctx.strokeStyle= "green";
ctx.lineWidth="2";
ctx.beginPath();
var lineHeight = height - k1;
ctx.moveTo(0, lineHeight);
ctx.lineTo(width, lineHeight);
ctx.stroke();
ctx.strokeStyle= "yellow";
ctx.lineWidth="2";
ctx.beginPath();
lineHeight = height - k2;
ctx.moveTo(0, lineHeight);
ctx.lineTo(width, lineHeight);
ctx.stroke();
ctx.strokeStyle= "red";
ctx.lineWidth="2";
ctx.beginPath();
lineHeight = height - k3;
ctx.moveTo(0, lineHeight);
ctx.lineTo(width, lineHeight);
ctx.stroke();
}
}
}

View file

@ -147,6 +147,8 @@
#include "Util.h"
#include "InterfaceParentFinder.h"
#include "FrameTimingsScriptingInterface.h"
// On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
// FIXME seems to be broken.
#if defined(Q_OS_WIN)
@ -1334,6 +1336,8 @@ void Application::initializeGL() {
InfoView::show(INFO_HELP_PATH, true);
}
FrameTimingsScriptingInterface _frameTimingsScriptingInterface;
extern void setupPreferences();
void Application::initializeUi() {
@ -1378,6 +1382,8 @@ void Application::initializeUi() {
rootContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
rootContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
rootContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
rootContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
rootContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface);
rootContext->setContextProperty("TREE_SCALE", TREE_SCALE);
rootContext->setContextProperty("Quat", new Quat());
@ -1421,6 +1427,7 @@ void Application::initializeUi() {
rootContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface());
rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
_glWidget->installEventFilter(offscreenUi.data());
offscreenUi->setMouseTranslator([=](const QPointF& pt) {
@ -1463,9 +1470,9 @@ void Application::initializeUi() {
});
}
void Application::paintGL() {
updateHeartbeat();
// Some plugins process message events, potentially leading to
// re-entering a paint event. don't allow further processing if this
// happens
@ -1483,6 +1490,7 @@ void Application::paintGL() {
_frameCount++;
_frameCounter.increment();
auto lastPaintBegin = usecTimestampNow();
PROFILE_RANGE_EX(__FUNCTION__, 0xff0000ff, (uint64_t)_frameCount);
PerformanceTimer perfTimer("paintGL");
@ -1735,6 +1743,9 @@ void Application::paintGL() {
batch.resetStages();
});
}
uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin;
_frameTimingsScriptingInterface.addValue(lastPaintDuration);
}
void Application::runTests() {

View file

@ -0,0 +1,53 @@
//
// Created by Bradley Austin Davis on 2016/04/04
// Copyright 2013-2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "FrameTimingsScriptingInterface.h"
#include <TextureCache.h>
void FrameTimingsScriptingInterface::start() {
_values.clear();
DependencyManager::get<TextureCache>()->setUnusedResourceCacheSize(0);
_values.reserve(8192);
_active = true;
}
void FrameTimingsScriptingInterface::addValue(uint64_t value) {
if (_active) {
_values.push_back(value);
}
}
void FrameTimingsScriptingInterface::finish() {
_active = false;
uint64_t total = 0;
_min = std::numeric_limits<uint64_t>::max();
_max = std::numeric_limits<uint64_t>::lowest();
size_t count = _values.size();
for (auto i = 0; i < count; ++i) {
const uint64_t& value = _values[i];
_max = std::max(_max, value);
_min = std::min(_min, value);
total += value;
}
_mean = (float)total / (float)count;
float deviationTotal = 0;
for (auto i = 0; i < count; ++i) {
float deviation = _values[i] - _mean;
deviationTotal += deviation*deviation;
}
_stdDev = sqrt(deviationTotal / (float)count);
}
QVariantList FrameTimingsScriptingInterface::getValues() const {
QVariantList result;
for (const auto& v : _values) {
result << v;
}
return result;
}

View file

@ -0,0 +1,38 @@
//
// Created by Bradley Austin Davis on 2016/04/04
// Copyright 2013-2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#include <stdint.h>
#include <QtCore/QObject>
class FrameTimingsScriptingInterface : public QObject {
Q_OBJECT
Q_PROPERTY(float mean READ getMean CONSTANT)
Q_PROPERTY(float max READ getMax CONSTANT)
Q_PROPERTY(float min READ getMin CONSTANT)
Q_PROPERTY(float standardDeviation READ getStandardDeviation CONSTANT)
public:
Q_INVOKABLE void start();
Q_INVOKABLE void addValue(uint64_t value);
Q_INVOKABLE void finish();
Q_INVOKABLE QVariantList getValues() const;
uint64_t getMax() const { return _max; }
uint64_t getMin() const { return _min; }
float getStandardDeviation() const { return _stdDev; }
float getMean() const { return _mean; }
protected:
std::vector<uint64_t> _values;
bool _active { false };
uint64_t _max { 0 };
uint64_t _min { 0 };
float _stdDev { 0 };
float _mean { 0 };
};

View file

@ -204,6 +204,15 @@ MyAvatar::~MyAvatar() {
_lookAtTargetAvatar.reset();
}
void MyAvatar::setOrientationVar(const QVariant& newOrientationVar) {
Avatar::setOrientation(quatFromVariant(newOrientationVar));
}
QVariant MyAvatar::getOrientationVar() const {
return quatToVariant(Avatar::getOrientation());
}
// virtual
void MyAvatar::simulateAttachments(float deltaTime) {
// don't update attachments here, do it in harvestResultsFromPhysicsSimulation()

View file

@ -105,6 +105,10 @@ public:
// thread safe
Q_INVOKABLE glm::mat4 getSensorToWorldMatrix() const;
Q_INVOKABLE void setOrientationVar(const QVariant& newOrientationVar);
Q_INVOKABLE QVariant getOrientationVar() const;
// Pass a recent sample of the HMD to the avatar.
// This can also update the avatar's position to follow the HMD
// as it moves through the world.

View file

@ -52,7 +52,8 @@ GLBackend::GLTexture::GLTexture(const Texture& texture) :
_target(gpuToGLTextureType(texture)),
_size(0),
_virtualSize(0),
_numLevels(texture.maxMip() + 1),
_numLevels(1),
//_numLevels(texture.maxMip() + 1),
_gpuTexture(texture)
{
Backend::incrementTextureGPUCount();
@ -254,7 +255,7 @@ void GLBackend::GLTexture::transfer() const {
}
if (_gpuTexture.isAutogenerateMips()) {
glGenerateMipmap(_target);
//glGenerateMipmap(_target);
(void)CHECK_GL_ERROR();
}
}
@ -435,7 +436,7 @@ void GLBackend::do_generateTextureMips(Batch& batch, size_t paramOffset) {
glActiveTexture(GL_TEXTURE0 + bindingSlot);
glBindTexture(object->_target, object->_texture);
glGenerateMipmap(object->_target);
//glGenerateMipmap(object->_target);
if (freeSlot < 0) {
// If had to use slot 0 then restore state