Rendering Performance

Version 1 (Redmine Admin, 11/23/2011 04:44 pm)

1 1
{{toc}}
2 1
3 1
Performance of rendering routines is quite crucial for a graphical application like QGIS. Therefore we should try to optimize it as much as possible. In following section you can find some benchmarks I have done on vector rendering, at the end there are several optimizations I think that might be useful to implement.
4 1
5 1
Area I've been studying was mainly drawing vector layer containing lines, but some optimizations should improve rendering speed in general. I haven't researched drawing of raster layers so far.
6 1
7 1
8 1
h2. Benchmarks 
9 1
10 1
For testing purposes I took a line vector layer that contains nearly 35 000 features (a roadmap). Such greater number of features can show where are the greater speed issues. Values I present here are averages of the values I have measured by doing refresh of map canvas while having the whole layer shown. I've tested on my AMD Athlon XP (1.83GHz) computer, with no CPU-intensive applications running. Map area in QGIS was about 900x530 pixels. These should just give an overview of the performance problems. Tests were done on debug version of QGIS with no optimizations.
11 1
12 1
*Test 1:* Vector provider speeds
13 1
14 1
|_. OGR (shapefile)|_. GRASS |_. Postgres
15 1
|1.97 s|1.53 s|1.26 s||
16 1
17 1
|
18 1
*Result:*
19 1
20 1
* PostgreSQL is as expected fastest
21 1
* First draw of newly loaded GRASS layer takes cca double time to complete (is there any caching happening?) 
22 1
23 1
Next tests were done with OGR provider (with shapefile driver), other providers give similar results with the same difference as above.
24 1
25 1
*Test 2:* on the fly projection
26 1
27 1
|_. Projections turned off|_. Using unprojected coordinate system|_. Using projected coordinate system
28 1
|1.97 s|ca 7 s|ca 11-14 s||
29 1
30 1
|
31 1
*Result:*
32 1
33 1
* on the fly projection is big performance killer
34 1
* results vary greatly depending on SRS being projected to 
35 1
36 1
*Test 3:* painting engines and antialiasing
37 1
38 1
39 1
||Antialiasing off|Antialiasing on|drawPolyline call (aa. off)|drawPolyline call (aa. on)|
40 1
|QPixmap|1.97 s|5.8 s|ca 0.2 s|3.51 s||
41 1
|QImage|1.74 s|2.18 s|cca 0.2 s|0.6 s||
42 1
|QGLPixelBuffer|2.03 s||
43 1
||0.24 s|
44 1
|
45 1
46 1
|
47 1
*Notes:*
48 1
49 1
* I have experimentally changed rendering to QImage instead of QPixmap, there's no option to change it at run-time
50 1
* QGLPixelBuffer doesn't bring better performance as I expected, even doesn't support antialiasing 
51 1
52 1
*Result:*
53 1
54 1
* QImage gives slightly better results without antialiasing
55 1
* QImage is MUCH better with antialiasing turned on
56 1
* it seems that rendering call is very fast - most of the time is spent with feature retreival and preparing for drawing 
57 1
58 1
*Test 4:* getting features with/without attributes
59 1
60 1
61 1
||no attributes|attr. for classification|all attributes|
62 1
|OGR|1.97 s|2.24 s|5.6 s||
63 1
64 1
|
65 1
66 1
*Notes:*
67 1
68 1
* test was done by changing getNextFeature draw in QgsVectorLayer::draw()
69 1
* results as expected
70 1
* need to benchmark also Postgres and GRASS provider for comparison 
71 1
72 1
73 1
h2. Tips for optimizing 
74 1
75 1
Here are some areas that might be optimized to speed up the rendering. I've done tests on some of the optimizations to prove they do a speedup (at least 0.1 sec)
76 1
77 1
* [done] use QImage instead of QPixmap
78 1
** main difference is that QPixmap is stored on X server, while QImage isn't. This means that QPixmap should be faster with drawing itself on screen, but QImage is faster for offscreen drawing
79 1
** after rendering QImage is converted to QPixmap to get drawing in on screen faster 
80 1
* pen with transparency should be initialized only once, not every time it comes to drawing
81 1
** where should be transparent pen created? in QgsVectorLayer, classes derived from QgsRenderer or in QgsSymbol?
82 1
** how to propagage easily transparency settings? 
83 1
* use getNextFeature call that don't create new feature every time
84 1
* resolve how caching of geometries should work - currently every render, cached geometry of features is deleted and then saved again. Also it's used only for layer editing, not drawing
85 1
* optimize OGR provider - add caching (probably with chance of setting cache size) for features
86 1
* review on the fly projections implementation to find out possible performance killers (or are those transformations really so intensive on CPU?)
87 1
* possibly add a feature to reproject the layers when loaded (or permanently) so on the fly projection will have a faster alternative 
88 1
89 1
Optimizations that don't work as I expected: :-)
90 1
91 1
* remove QgsClipper as it's not needed anymore
92 1
** reason 1: we should use QImage for drawing and it doesn't depend on X server
93 1
** reason 2: drawing to QPixmap should be also OK as X11ZoomBug refers to Qt3 documentation that states that it will be resolved in Qt4
94 1
** Actually it's still needed because of bug in rasterizer for QImage - it makes application crash when zoomed in too much. Thanks Gavin for finding this problem. 
95 1
96 1
*Comments by Tim:*
97 1
98 1
* Did you build spatial indexes for the ogr test? It can make a very big difference to performance.
99 1
** MD: Building spatial index doesn't make sense in this case since all features from layer were drawn. 
100 1
* I agree the pen transparency stuff I did is not well optimised for performance
101 1
* Getting rendering speed of rasters to the pre canvas merge state would be nice. I will revisit my render code in raster to see if I can draw stratight to qimage. If I reacall correctly it actually does draw to qimage then renders onto qpixmmap paint device afterwards.