-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Clean up QgsExpressionContext in QgsServer::handleRequest
- Loading branch information
Showing
1 changed file
with
7 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where exactly are the items added?
This is probably a workaround that only masks the real issue.
They probably should be pushing a new scope and popping it after usage.
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This commit commes from a PR #3181
with this description:
Each call to QgsMapLayer::draw add items to QgsExpressionContext scope.
The scope is not cleaned between request and thus the scope list to grow indefinitely.
Having the list growing indefinitely deteriorate seriously performances in the long run. It also increase the memory footprint but in a less noticiable way.
This behavior has been checked by monitoring reponse time of several ten of thousand identical requests during server long runs.
Not sure it this is the most elegant way of fixing this but it does the job.
I'm writing an email about t and other degradation of performance in QGIS Server.
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have copied the question there so we can track the issue to its roots.
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I have the felling that there is not legitimate reason for the item not to be removed at some point.
QgsVectorLayer::draw creates a QgsVectorLayerRenderer. The item is added in QgsVectorLayerRenderer constructor (https://github.com/qgis/QGIS/blob/master/src/core/qgsvectorlayerrenderer.cpp#L103) but seems to be never removed.
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have the feeling that
QgsVectorLayerRenderer::mContext
should be a copy and not a reference to the context. https://github.com/qgis/QGIS/blob/master/src/core/qgsvectorlayerrenderer.h#L1015c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmarteau can you check if this approach also works:
#3182
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mine is that the the layer scope is misplaced: it should be added/popped in the draw() function
adding/removing scope should be QgsVectorLayerRenderer::draw function (the same way the function QgsVectorLayerRenderer::drawRendererV2 add/pop 'symbolScope').
IMHO, there is no point to add a scope in the constructor.
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#3182: I like enforcing immutability as much as possible but actually drawRendererV2 mutate the context.
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the context is also used in other methods like render()
Then the question is probably, why? :)
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, It was about render(), not draw().
I don't know enough about the purpose of the context in this game to have a clear idea of what to do but:
the context is passed around in lot of method and object and I'm affraid that passing that object by reference somewhere and by copy elsewhere may be confusing. Furthermore, I have concerns about the overhead of copying object at each invocation.
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copy happens once per layer rendering. Adding the scope in
render()
would be once for each feature being rendered, if there's actually an impact on performance, I'd be more afraid of the second one.Is it still passed as reference in other places?
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, in a lot of places (as mutable object), mostly rendering functions.
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's see what @wonder-sk and @nyalldawson think
5c3aa51
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say ``QgsRenderContext` is a kind of class where nobody has defined its rules for using it properly, so we use it in various ways. It is kind of a place where to dump random stuff needed during rendering :-)
In this particular case, wouldn't it be the best to just clean up the expression context in the rendering class that added items?
The problem would also go away with a switch to the renderer job classes introduced in 2.4, but I understand it may take a while to switch to those. (the renderer jobs create their own contexts when needed).
Finally, it would probably make sense to look at changing
QgsRenderContext
for 3.0. It has fair amount of redundancy withQgsMapSettings
and in various places (e.g. labeling) these two are used together. We could embedQgsMapSettings
intoQgsRenderContext
and get rid of the duplicated variables.