Initialize scale factor to the last scale factor set on any instance
ClosedPublic

Authored by hein on Dec 2 2017, 10:18 PM.

Details

Summary

Plasma::Svg initializes SvgPrivate::scaleFactor to 1.0. On systems with
a higher value for Units:devicePixelRatio, that means Svg::setScaleFactor
gets called with a different value right after instanciation and a fair
amount of work is done twice.

This patch introduces a static SvgPrivate::s_lastScaleFactor,
initialized to 1.0 but updated in Svg::setScaleFactor.
SvgPrivate::scaleFactor is then initialized to the static every time
its instanciated. That means after the first time Svg::setScaleFactor
is called with e.g. 2.0, subsequent Svg instances get initialized
with 2.0.

This ends up shaving a decent amount of time off of startup on scaled
systems.

Diff Detail

Repository
R242 Plasma Framework (Library)
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
hein created this revision.Dec 2 2017, 10:18 PM
Restricted Application added projects: Plasma, Frameworks. · View Herald TranscriptDec 2 2017, 10:18 PM
Restricted Application added a subscriber: Frameworks. · View Herald Transcript
hein requested review of this revision.Dec 2 2017, 10:18 PM
mart accepted this revision.Dec 2 2017, 10:22 PM
This revision is now accepted and ready to land.Dec 2 2017, 10:22 PM
davidedmundson requested changes to this revision.Dec 2 2017, 10:36 PM

Use of static is a hack.

If this fixes anything, it means there's a bug elsewhere that needs finding.

This revision now requires changes to proceed.Dec 2 2017, 10:36 PM

I agree with David that this is a hack. Also I think it will fail for multi screen with different dpi.

hein added a comment.Dec 3 2017, 10:21 AM

Personally, I disagree it's hack. It's just defensively written: It makes sure users of the Svg API don't need to understand the order in which they need to call setScaleFactor and setImagePath for good performance. For something performance-critical I'd prefer not to have to check every six months whether everyone is using it correctly. Sure, cleaning up the call site is nice anyway, but it won't guard against future call sites being wrong. Self-tuning code is smart and practical.

It's also going to work fine with multiple screens. Svgs are usually instanciated in batches. If it's a screen with a different scale factor the first in the batch will hit the old slow path, all subsequent ones will be fast.

how is this one method different from setSize setColorGroup setContainsMultipleImages setUseSystemColors etc.?

hein added a comment.Dec 3 2017, 10:30 AM

how is this one method different from setSize setColorGroup setContainsMultipleImages setUseSystemColors etc.?

Most of those don't show up at 2% during my plasmashell startup. The scale factor penalty hits *every SVG* on a scaled system.

hein added a comment.Dec 3 2017, 2:57 PM

So I worked out why this happens. We have API like this:

SvgItem {

svg: Svg { imagePath: "..." }

}

Without my patch, Svg is instanciated with a scale factor of 1.0 always. Then setImagePath is called on it first. Then SvgItem::setSvg is called with the Svg instance and calls setScaleFactor on it.

In this pattern, SvgItem doesn't get a chance to set the scale factor before imagePath, because it's not the one setting the latter.

The only call site fix here would be to implement QQmlParserStatus in Svg and then set scaleFactor from QML everywhere by accessing Units. But this hygiene would be really hard to enforce, especially in third-party widgets.

I still consider my patch to be a fairly pragmatic solution to this.

This revision was automatically updated to reflect the committed changes.
hein reopened this revision.Dec 3 2017, 6:00 PM

Sorry, accidental push. I'll revert and reopen this.

davidedmundson accepted this revision.Dec 4 2017, 5:35 PM
This revision is now accepted and ready to land.Dec 4 2017, 5:35 PM
This revision was automatically updated to reflect the committed changes.