forked from qt-creator/qt-creator
QmlProfiler: Draw Overview in multiple passes
If there are too many events it takes too long to draw the overview. By drawing only part of the events in each paint callback and scheduling multiple paints we can mitigate that. The result is that a rough outline is visible immediately and the details are filled in bit by bit. Task-number: QTCREATORBUG-12341 Change-Id: Id94d914e2926be01cb1635fbd8814c4d2f57d23b Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
@@ -32,16 +32,16 @@
|
|||||||
var qmlProfilerModelProxy = 0;
|
var qmlProfilerModelProxy = 0;
|
||||||
|
|
||||||
//draw background of the graph
|
//draw background of the graph
|
||||||
function drawGraph(canvas, ctxt, region)
|
function drawGraph(canvas, ctxt)
|
||||||
{
|
{
|
||||||
ctxt.fillStyle = "#eaeaea";
|
ctxt.fillStyle = "#eaeaea";
|
||||||
ctxt.fillRect(0, 0, canvas.width, canvas.height);
|
ctxt.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
//draw the actual data to be graphed
|
//draw the actual data to be graphed
|
||||||
function drawData(canvas, ctxt, region)
|
function drawData(canvas, ctxt)
|
||||||
{
|
{
|
||||||
if ((!qmlProfilerModelProxy) || qmlProfilerModelProxy.count() == 0)
|
if ((!qmlProfilerModelProxy) || qmlProfilerModelProxy.count() === 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var width = canvas.width;
|
var width = canvas.width;
|
||||||
@@ -54,17 +54,15 @@ function drawData(canvas, ctxt, region)
|
|||||||
var spacing = width / qmlProfilerModelProxy.traceDuration();
|
var spacing = width / qmlProfilerModelProxy.traceDuration();
|
||||||
|
|
||||||
var modelRowStart = 0;
|
var modelRowStart = 0;
|
||||||
for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex++) {
|
|
||||||
for (var ii = 0; ii < qmlProfilerModelProxy.count(modelIndex); ++ii) {
|
for (var modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); ++modelIndex) {
|
||||||
|
for (var ii = canvas.offset; ii < qmlProfilerModelProxy.count(modelIndex);
|
||||||
|
ii += canvas.increment) {
|
||||||
|
|
||||||
var xx = (qmlProfilerModelProxy.getStartTime(modelIndex,ii) -
|
var xx = (qmlProfilerModelProxy.getStartTime(modelIndex,ii) -
|
||||||
qmlProfilerModelProxy.traceStartTime()) * spacing;
|
qmlProfilerModelProxy.traceStartTime()) * spacing;
|
||||||
if (xx > region.x + region.width)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var eventWidth = qmlProfilerModelProxy.getDuration(modelIndex,ii) * spacing;
|
var eventWidth = qmlProfilerModelProxy.getDuration(modelIndex,ii) * spacing;
|
||||||
if (xx + eventWidth < region.x)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (eventWidth < 1)
|
if (eventWidth < 1)
|
||||||
eventWidth = 1;
|
eventWidth = 1;
|
||||||
@@ -88,8 +86,9 @@ function drawData(canvas, ctxt, region)
|
|||||||
ctxt.lineWidth = 2;
|
ctxt.lineWidth = 2;
|
||||||
var radius = 1;
|
var radius = 1;
|
||||||
modelRowStart = 0;
|
modelRowStart = 0;
|
||||||
for (modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex++) {
|
for (modelIndex = 0; modelIndex < qmlProfilerModelProxy.modelCount(); modelIndex += 10) {
|
||||||
for (ii = 0; ii < qmlProfilerModelProxy.count(modelIndex); ++ii) {
|
for (ii = canvas.offset; ii < qmlProfilerModelProxy.count(modelIndex);
|
||||||
|
ii += canvas.increment) {
|
||||||
if (qmlProfilerModelProxy.getBindingLoopDest(modelIndex,ii) >= 0) {
|
if (qmlProfilerModelProxy.getBindingLoopDest(modelIndex,ii) >= 0) {
|
||||||
var xcenter = Math.round(qmlProfilerModelProxy.getStartTime(modelIndex,ii) +
|
var xcenter = Math.round(qmlProfilerModelProxy.getStartTime(modelIndex,ii) +
|
||||||
qmlProfilerModelProxy.getDuration(modelIndex,ii) -
|
qmlProfilerModelProxy.getDuration(modelIndex,ii) -
|
||||||
@@ -107,7 +106,7 @@ function drawData(canvas, ctxt, region)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawTimeBar(canvas, ctxt, region)
|
function drawTimeBar(canvas, ctxt)
|
||||||
{
|
{
|
||||||
if (!qmlProfilerModelProxy)
|
if (!qmlProfilerModelProxy)
|
||||||
return;
|
return;
|
||||||
@@ -172,11 +171,3 @@ function prettyPrintTime( t )
|
|||||||
t = Math.floor(t - m*60);
|
t = Math.floor(t - m*60);
|
||||||
return m+"m"+t+"s";
|
return m+"m"+t+"s";
|
||||||
}
|
}
|
||||||
|
|
||||||
function plot(canvas, ctxt, region)
|
|
||||||
{
|
|
||||||
drawGraph(canvas, ctxt, region);
|
|
||||||
drawData(canvas, ctxt, region);
|
|
||||||
drawTimeBar(canvas, ctxt, region);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ Canvas {
|
|||||||
objectName: "Overview"
|
objectName: "Overview"
|
||||||
contextType: "2d"
|
contextType: "2d"
|
||||||
|
|
||||||
|
property int eventsPerPass: 4096
|
||||||
|
property int increment: -1
|
||||||
|
property int offset: -1
|
||||||
|
|
||||||
// ***** properties
|
// ***** properties
|
||||||
height: 50
|
height: 50
|
||||||
property bool dataReady: false
|
property bool dataReady: false
|
||||||
@@ -43,10 +47,14 @@ Canvas {
|
|||||||
property double endTime : 0
|
property double endTime : 0
|
||||||
property bool recursionGuard: false
|
property bool recursionGuard: false
|
||||||
|
|
||||||
|
onWidthChanged: offset = -1
|
||||||
|
|
||||||
// ***** functions
|
// ***** functions
|
||||||
function clear()
|
function clear()
|
||||||
{
|
{
|
||||||
dataReady = false;
|
dataReady = false;
|
||||||
|
increment = -1;
|
||||||
|
offset = -1;
|
||||||
requestPaint();
|
requestPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,23 +96,40 @@ Canvas {
|
|||||||
Connections {
|
Connections {
|
||||||
target: qmlProfilerModelProxy
|
target: qmlProfilerModelProxy
|
||||||
onDataAvailable: {
|
onDataAvailable: {
|
||||||
dataReady = true;
|
dataReady = true;
|
||||||
requestPaint();
|
increment = Math.ceil(qmlProfilerModelProxy.count() / eventsPerPass);
|
||||||
|
offset = -1;
|
||||||
|
requestPaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: paintTimer
|
||||||
|
onTriggered: canvas.requestPaint();
|
||||||
|
}
|
||||||
|
|
||||||
// ***** slots
|
// ***** slots
|
||||||
onPaint: {
|
onPaint: {
|
||||||
if (context === null)
|
if (context === null)
|
||||||
return; // canvas isn't ready
|
return; // canvas isn't ready
|
||||||
|
|
||||||
context.reset();
|
|
||||||
Plotter.qmlProfilerModelProxy = qmlProfilerModelProxy;
|
Plotter.qmlProfilerModelProxy = qmlProfilerModelProxy;
|
||||||
if (dataReady) {
|
|
||||||
Plotter.plot(canvas, context, region);
|
if (offset < 0) {
|
||||||
} else {
|
context.reset();
|
||||||
Plotter.drawGraph(canvas, context, region) //just draw the background
|
Plotter.drawGraph(canvas, context);
|
||||||
|
if (dataReady) {
|
||||||
|
Plotter.drawTimeBar(canvas, context);
|
||||||
|
offset = 0;
|
||||||
|
// Larger initial delay to avoid flickering on resize
|
||||||
|
paintTimer.interval = 1000;
|
||||||
|
paintTimer.start();
|
||||||
|
}
|
||||||
|
} else if (offset < increment) {
|
||||||
|
Plotter.drawData(canvas, context);
|
||||||
|
++offset;
|
||||||
|
paintTimer.interval = 1;
|
||||||
|
paintTimer.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user