Merge lp:~adamreichold/qpdfview/track-exposed-tiles into lp:qpdfview

Proposed by Adam Reichold
Status: Merged
Merged at revision: 1858
Proposed branch: lp:~adamreichold/qpdfview/track-exposed-tiles
Merge into: lp:qpdfview
Diff against target: 74 lines (+20/-4)
2 files modified
sources/pageitem.cpp (+18/-4)
sources/pageitem.h (+2/-0)
To merge this branch: bzr merge lp:~adamreichold/qpdfview/track-exposed-tiles
Reviewer Review Type Date Requested Status
Razi Alavizadeh Pending
Review via email: mp+248199@code.launchpad.net

Description of the change

After noticing that the interface begins to "stutter" using high scale factors (roughly above 1000%) and isolating this to using tiling and continuous layout, I noticed during profiling that cancellation has a pretty large overhead. This was somewhat reduced by making sure that the atomic operations to set cancellation were inlined, but even then the atomic operations to cancel and to reset instances of "QPixmap" are still noticable.

It seems the main cause of this is the document view calling "PageItem::cancelRender" on all not-visible page items and with a high scale factor implying a large number of tiles (e.g. 500 tiles per page at 1200%), this easily yields 100000 tiles being cancelled even though rendering on them was not active at all.

This branch tries to alleviate the issue by making the page item explicitly track the exposed tiles and letting the document view cancel only those (for non-force cancellation, i.e. without interrupting prefetching which in itself is a problem with a high tile count) that were actually exposed. The page item itself will also cancel tiles when and only when they are removed from the set of exposed tiles which again reduces the number of pointless cancellation attempts.

The necessary changes are pretty limited, but as they touch a very fundamental function of the program, I would be grateful for a review and test by another developer.

To post a comment you must log in.
1858. By Adam Reichold

Also clear set of exposed tiles after cancellation.

1859. By Adam Reichold

Remerge with trunk to suppress unrelated change.

Revision history for this message
Adam Reichold (adamreichold) wrote :

Maybe we should also consider making "TileItem::cancelRender" inline since even after these optimizations, it shows up on top of gprof's list. I strongly dislike this since it exposes the "RenderTask" internals of "TileItem", but then again "tileitem.h" (and hence indirectly "rendertask.h") are included into "tileitem.cpp" and "pageitem.cpp" only.

It seems like a sensible and pratically free optimization, but it also does not seem to noticeably reduce the "stutter" in any way, so I am very much unsure about it.

Revision history for this message
Razi Alavizadeh (srazi) wrote :

Your patch seems OK. but I didn't see a big difference here. I think maybe the solution is using a limit for number of "tile"s? Because when testing this branch I found that when using a high scale e.g. 1200% "qpdfview.exe" uses more than 120,000 handles and if I change scale factor to 1933% there will be more than 300,000 handles used by qpdfview.exe

Revision history for this message
Adam Reichold (adamreichold) wrote :

Hello,

that's strange as on my system this patch made the difference between stuttering and being able to set that we might need better double-buffering as well. :-\

When you say handles, I suppose you mean Windows HANDLE data type? Do you to which kind of resource these handles refered?

In any case, I think adapting the tile size would be nicer than a hard limit, e.g. using 16 MB instead of 4 MB tiles above some specific number of tiles per page. I am not sure whether I will implement this for 0.4.14 depending on how difficult it is.

In any case, I'll merge this and make "TileItem::cancelRender" inline. I also think the signal-slot invocation using "QTimer::singleShot" within "TileItem::deleteAfterRender" could be replaced by a simple flag to further reduce overhead.

Thanks for the review! Best regards, Adam.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'sources/pageitem.cpp'
--- sources/pageitem.cpp 2015-02-01 13:27:13 +0000
+++ sources/pageitem.cpp 2015-02-01 13:33:19 +0000
@@ -334,10 +334,12 @@
334 }334 }
335 else335 else
336 {336 {
337 foreach(TileItem* tile, m_tileItems)337 foreach(TileItem* tile, m_exposedTileItems)
338 {338 {
339 tile->cancelRender();339 tile->cancelRender();
340 }340 }
341
342 m_exposedTileItems.clear();
341 }343 }
342}344}
343345
@@ -1121,6 +1123,8 @@
1121 m_tileItems.replace(index, new TileItem(this));1123 m_tileItems.replace(index, new TileItem(this));
1122 }1124 }
11231125
1126 m_exposedTileItems.clear();
1127
1124 if(oldCount != newCount)1128 if(oldCount != newCount)
1125 {1129 {
1126 foreach(TileItem* tile, m_tileItems)1130 foreach(TileItem* tile, m_tileItems)
@@ -1173,15 +1177,25 @@
11731177
1174 foreach(TileItem* tile, m_tileItems)1178 foreach(TileItem* tile, m_tileItems)
1175 {1179 {
1176 if(translatedExposedRect.intersects(tile->rect()))1180 const bool intersects = translatedExposedRect.intersects(tile->rect());
1181 const bool contains = m_exposedTileItems.contains(tile);
1182
1183 if(intersects && !contains)
1177 {1184 {
1178 tile->paint(painter, m_boundingRect.topLeft());1185 m_exposedTileItems.insert(tile);
1179 }1186 }
1180 else1187 else if(!intersects && contains)
1181 {1188 {
1189 m_exposedTileItems.remove(tile);
1190
1182 tile->cancelRender();1191 tile->cancelRender();
1183 }1192 }
1184 }1193 }
1194
1195 foreach(TileItem* tile, m_exposedTileItems)
1196 {
1197 tile->paint(painter, m_boundingRect.topLeft());
1198 }
1185 }1199 }
11861200
1187 if(s_settings->pageItem().decoratePages() && !presentationMode())1201 if(s_settings->pageItem().decoratePages() && !presentationMode())
11881202
=== modified file 'sources/pageitem.h'
--- sources/pageitem.h 2014-11-15 11:12:55 +0000
+++ sources/pageitem.h 2015-02-01 13:33:19 +0000
@@ -25,6 +25,7 @@
25#include <QCache>25#include <QCache>
26#include <QGraphicsObject>26#include <QGraphicsObject>
27#include <QIcon>27#include <QIcon>
28#include <QSet>
2829
29class QGraphicsProxyWidget;30class QGraphicsProxyWidget;
3031
@@ -210,6 +211,7 @@
210 void prepareGeometry();211 void prepareGeometry();
211212
212 QVector< TileItem* > m_tileItems;213 QVector< TileItem* > m_tileItems;
214 mutable QSet< TileItem* > m_exposedTileItems;
213215
214 void prepareTiling();216 void prepareTiling();
215217

Subscribers

People subscribed via source and target branches

to all changes: