QML Canvas Element and Javascript Performance
-
wrote on 14 Dec 2011, 19:29 last edited by
Hi,
I've been playing around a bit with the QML Canvas element ("http://qt.gitorious.org/qt-labs/qmlcanvas":http://qt.gitorious.org/qt-labs/qmlcanvas). I started by modifying the graph example so that it produces a line graph that is updated as fast as possible with random data. I've found that the update rate gets very very slow as the number of points increases (for 250 points ~6 updates/second on my desktop machine!). Here is the code:
@
import "./Canvas"
import Qt 4.7Canvas {
width:600
height:400
property int count: 250
property int graphPadding: 20
property variant lastTime
property variant currentTimeTimer { interval: 1; running: true; repeat: true; onTriggered: requestPaint() } Component.onCompleted: { marker.minimumX = graphPadding marker.maximumX = width - graphPadding - marker.width lastTime = new Date() currentTime = new Date() } Text { id: updatesPerSecond anchors.right: parent.right anchors.top: parent.top text: "" color: "white" } onPaint: { currentTime = new Date() updatesPerSecond.text = (1000/(currentTime - lastTime)).toFixed(1) + " updates/second" lastTime = currentTime var ctx = getContext(); var tickWidth = 20; var numTicks = 10; var cHeight = height; var cWidth = width; ctx.fillStyle = '#000'; ctx.fillRect(0, 0, width, height); ctx.strokeStyle = "rgb(150,150,150)"; ctx.lineWidth = 1; // Draw Axis ctx.beginPath(); ctx.moveTo(graphPadding, graphPadding); ctx.lineTo(graphPadding,cHeight - graphPadding); ctx.lineTo(cWidth - graphPadding, cHeight - graphPadding); ctx.stroke(); ctx.closePath(); // Draw ticks var tickSpacing = (cHeight - graphPadding*2)/(numTicks+1); ctx.beginPath(); for(var i = 0; i <= numTicks; i++) { ctx.moveTo(graphPadding - tickWidth/2, graphPadding + tickSpacing*i); ctx.lineTo(graphPadding + tickWidth/2, graphPadding + tickSpacing*i); } ctx.stroke(); ctx.closePath(); // Draw gridlines ctx.beginPath(); for(var i = 0; i <= numTicks; i++) { ctx.moveTo(graphPadding + tickWidth/2, graphPadding + tickSpacing*i); ctx.lineTo(cWidth - graphPadding, graphPadding + tickSpacing*i); } ctx.stroke(); ctx.closePath(); // Draw trace (with random data) var horizSpace = (cWidth - graphPadding * 2)/count var vertSpace = cHeight - (graphPadding * 2); var xPos = graphPadding var yPercent = 0 var yPos = 0 ctx.strokeStyle = '#ffff00' ctx.beginPath(); for(var i = 0;i < count;i++) { yPercent = 100 - Math.floor(Math.random()*100) yPos = (vertSpace * (yPercent / 100) + (graphPadding)); if(i == 0) ctx.moveTo(xPos, yPos); else ctx.lineTo(xPos, yPos); xPos += horizSpace; } ctx.stroke(); ctx.closePath(); }
}
@After trying different things out, I've found that the culprit is the line
@
yPercent = 100 - Math.floor(Math.random()*100)
@If I comment out the Math function calls and replace with a constant, the update rate goes up to ~60 updates/second. Why is this Javascript so slow? Is there anything I can do to increase the performance of random data generation (i.e., going to C++?)?
As a side note, I've also noticed that if I try resizing the canvas window most of the screen will go white and I get the following error message in the output:
"QPixmap::operator=: Cannot assign to pixmap during painting"
I would have expected the canvas to resize and redraw correctly, but perhaps I don't understand the implementation well enough. Is there anything I can do to make the canvas resizing work as expected?
Thanks!
-
wrote on 17 Dec 2011, 18:28 last edited by
I don't know why javascript is slow, but i'm guessing this will improve since Qt 5 is here with the V8 engine. (yes, the google javascript engine that they made for chrome)
Anyway, a "solution" i can think of is just making a C++ function for it and call that. Or different (don't know if it's better), make a list of random values in C++, make that list available in QML and just use that for your random values.
Good luck!
-
wrote on 8 Feb 2012, 03:10 last edited by
Hi,
The http://qt.gitorious.org/qt-labs/qmlcanvas is a demo project and totally unpolished and discontinued. You can still use it with QtQuick 1.0, but for QtQuick2, there is already a builtin Canvas item to do the same thing. With many improvements in Qt5 (scene graph, v8, etc) the performance will be better and more completed in features.See the online documentation for more details:
http://doc.qt.nokia.com/5.0-snapshot/qml-qtquick2-canvas.html
-
wrote on 29 Aug 2013, 11:19 last edited by
Sadly I'm using the QtQuick2 Canvas item in Qt 5.1 and performance is still pretty terrible. I'd recommend using C++ for any custom widgets.