[Qgis-psc] 2019 Grant Final reports: Rendering optimisation and labeling work

Nyall Dawson nyall.dawson at gmail.com
Mon Dec 2 18:25:31 PST 2019

Hi PSC, devs,

Following the submission of the last part of our 2019 grant work, here's a
report detailing what was undertaken and achieved thanks to these two
funding grants:

*Profile and optimise the QGIS vector rendering code*

One of the most critical and important functions in the QGIS application is
rendering of vector map layers. QGIS has an extremely powerful and flexible
vector symbology engine, capable of some mind blowing cartography and
visual effects. For efficient use on both the desktop and server, users
require that QGIS rendering is as fast as it possibly can be!

During this grant project, we conducted in-depth research into code "hot
spots" and inefficiencies in the QGIS rendering code using a number of code
profiling tools. This work resulted in many optimisations, including:

   - Cache painter path for font marker when it doesn't change (
   https://github.com/qgis/QGIS/pull/30860) - around 2x speed up for font
   marker rendering
   - Optimise checking for active properties (
   - Fix expensive file modified time check is applied with every check of
   svg/image cache (https://github.com/qgis/QGIS/pull/30862) - dramatic
   speed up for SVG marker rendering (and SVG rendering across QGIS in general)
   - Optimise reading of multipoints from OGR (
   https://github.com/qgis/QGIS/pull/30863) - speeds up use of multipoint
   layers across QGIS in general (not just rendering)
   - Don't perform costly calculation of symbol output units which we don't
   use (https://github.com/qgis/QGIS/pull/30864) - speeds up all vector
   rendering operations
   - Fix unnecessary calculation of marker symbol bounds when labeling is
   not required for a layer and symbols layers are in place (
   https://github.com/qgis/QGIS/pull/30865) - speeds up rendering of simple
   marker points matching this situation by around 3x
   - Fix large speed regression in evaluating string equality expressions (
   https://github.com/qgis/QGIS/pull/30866) - dramatic improvement of
   expression calculation times across all of QGIS
   - Avoid expensive symbol clones during label rendering (
   - Speed up copying of paint effects (
   - Add a reserve method to QgsGeometryCollection (
   https://github.com/qgis/QGIS/pull/30892) - speeds up use of multi
   geometry types across all of QGIS
   - Avoid storing and cloning paint effects for layers if they are just
   the default stack unchanged (https://github.com/qgis/QGIS/pull/30896)
   - Optimizations for shapeburst rendering (
   - Much faster copying of expression contexts with a project scope
   present (https://github.com/qgis/QGIS/pull/30983)
   - Avoid lots of unnecessary work involving disabled label data defined
   properties (https://github.com/qgis/QGIS/pull/30986)
   - Optimisations to QgsProperty which greatly speed up data defined
   symbology rendering in some circumstances (
   - Big speedup when loading symbols with embedded paths
   - Add a fast shortcut to rectangle/geometry intersection test (
   - Speed up geometry equality checks by orders of magnitude (
   - Speed up geometry operations involved in tracing and snapping (
   - Avoid using expensive geos polygon overlap calculation for two
   horizontal labels (https://github.com/qgis/QGIS/pull/31937) - speeds up
   label rendering on complex maps
   - Limit number of label candidates for large layers (
   https://github.com/qgis/QGIS/pull/31975) - on complex projects can
   reduce label rendering time by an order of magnitude

While the focus of this work was on the vector rendering code, some of the
optimisations implemented have resulted in dramatic improvements across
other parts of QGIS also (such as certain Processing algorithms).

These optimisations were made available in the QGIS 3.10.0 release, with
selected low-risk optimisations also being backported to the QGIS 3.4 LTR

*"Rebalance" the labeling engine and fix poor automatic label placement

While QGIS has a powerful engine sitting behind its automatic label
placement, the labeling results generated by this engine were often
unpredictable and frustrating for users. Labels were frequently positioned
over other features, and regardless of how heavily users tweaked the
various label settings it could be impossible to avoid these unwanted
labels. Furthermore, the settings for controlling individual layer label
and feature obstacle priorities generally had no discernible effect on the
actual placement of labels on the map.

During this work project we commenced by safe guarding the existing label
placement logic with a series of new carefully designed unit tests covering
a range of different label placement situations. We then used these
reference tests as a guide and re-worked the label placement engine
logic. Now, labels will never be placed over features from a layer with a a
higher obstacle weight when compared to the label's priority.

This logic dramatically simplifies the effect of labeling settings for
users, avoiding the complexities and bugs which were present in the older

In order to avoid disrupting existing projects, the new labeling logic is
only used for newly created projects in QGIS 3.12 and later. We added a
mechanism to allow users to manually upgrade existing projects to the newer
logic, via the project's label settings dialog.

Lastly, we used this opportunity to invest some much-needed time in
modernising and cleaning up the labeling engine code, to help make it
easier to understand and maintain in future.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-psc/attachments/20191203/47661ecc/attachment.html>

More information about the Qgis-psc mailing list