On 7/6/2011 2:57 PM, Jeremy Sanders wrote:
Benjamin K. Stuhl wrote:

One other possibility is to have each widget render to a QPicture in the
UI thread and then offload the QPicture-to-QImage rendering (which is
probably the expensive part, especially if antialiasing is turned on) to a
background thread. The PlotWindow would just recomposite whenever it got a
new layer from the background thread; each rendering request should
probably be tagged with the widget's changeset number so that the
rendering thread can throw out already-out-of-date requests.

This seems to be quite a good idea. I've done some benchmarks. Repeatedly
drawing some examples, the multixy and multiaxes examples are 8% faster
using QPicture, sin is 2% faster. A test with 40000 points is 2% slower.

It seems a little strange that it is often faster rendering to a QPicture,
then drawing to a QPixmap, rather than drawing directly. Perhaps it is some
sort of improved cache locality within Qt.

This is indeed rather surprising. I expected QPicture-based drawing to be trade extra CPU overhead for better multicore behavior, but if it improves even single-core performance, that's great!

It shouldn't be hard to separate the rendering out to another thread in this
case.

The one problem I can think of is the question of how to terminate a
rendering thread if the document has changed. It looks like
QThread.terminate is dangerous, so should be avoided. We could fire off a
thread each time the document changes, but it could make single core
machines a bit busy. I wonder whether it is possible to raise an exception
in a different thread - seems doubtful. The only solution I can think of is
to check for some sort of stop signal at entry to rendering each widget, and
raise an exception if it is present, falling back to rendering the next
QPicture.

As you said, the thread would spend all its time in QPainter.drawPicture(). However, I would suggest that rather than firing off a thread for each redraw, there just be a fixed number (1?) of drawing threads: each redraw queues a QPicture rendering request tagged with a widget id. The rendering thread pulls requests off the queue, but rather than service them in simple FIFO order, on each pull it finds the most recent request with the given widget id and drops all the older requests. That at least prevents the thread from ever being more than one frame behind in its rendering...

I see that you're working on encapsulating the drawing better; if you want to pull my finer-changesets work to help that along, feel free.

Regards,
-- BKS

_______________________________________________
Veusz-discuss mailing list
[email protected]
https://mail.gna.org/listinfo/veusz-discuss

Répondre à