Page preloading

Asked by Carli Samuele

Hello!
qpdfview is great, I really love it!

My question is: I often work with really heavy (read graphic intense) stuff (slides), with antialiasing my i7-3930k (not the slowest one on the market, just to say) can take up to a few seconds to render a slide.
I did set the cache size to 512 and enable prefetch, but still it feels like it is waiting for my click to show the next slide to compute the rendering, hence the slide change time can be of several seconds,
Is there a reason why the slide is not being precomputed?

At the same time, a multiple page overview can take some time to compute, and is usually computing only a few pages using only one processor. Is there any plan/option to have parallel computation of different pages, as well as precomputation of a whole document (at least until some memory limit is reached)?

Thanks!
Sam

Question information

Language:
English Edit question
Status:
Solved
For:
qpdfview Edit question
Assignee:
Adam Reichold Edit question
Solved by:
Carli Samuele
Solved:
Last query:
Last reply:
Revision history for this message
Benjamin Eltzner (b-eltzner) said :
#1

Hi,

1) If I understnad you correctly, the lack of prefetching occurs in presentation mode. I can confirm, that prefetching does not seem to work in presentation mode. This might be a bug. (Adam?)
2) If I remember correctly, prefetching only caches one page preceeding and one page following the current page. Increasing cache size will increase the number of documents for which this set of adjacent pages can be cached simultaneously, but not the number of pages cached for a single document. If I remember correctly, this decision was made because files with pages that take seconds to render are supposedly rare. (again: Adam?)
3) The lack of multithreading is due to the poppler library. This https://bugs.freedesktop.org/show_bug.cgi?id=50992 discussion indicates, that the library will be thread safe from version 0.24 on. As libpoppler 0.22 has just been released, this will probably not hit Ubuntu before 14.04.
4) As a Qt based program, qpdfview unfortunately has to rely on the splash backend of the poppler library for rendering, which is not very well integrated. The same holds for Okular, while Evince, using the Cairo backend, frequently displays better rendering performance. If you are not afraid of "installing half of Gnome" and you can do without tabs if necessary, you might want to give Evince a shot for really heavy stuff.

Cheers, Benjamin

Revision history for this message
Benjamin Eltzner (b-eltzner) said :
#2

Correction for 2) Pages that have been rendered stay in cache, until it is full. However, cache size has no influence on prefetching.

Revision history for this message
Adam Reichold (adamreichold) said :
#3

To expand on Benjamin's answers: The problem is the presentation view, is does not cache and hence can't prefetch. So your observations are entirely correct. It is not a bug, we did not add this to keep the presentation view as simple as possible as we are/were aiming for minimal code size. I'll see whether I can do something about that in the next release.

As for the main view, the cache is shared between all documents and has one entry for each page. It will cache pages as long as there is room and free them on a last-recently-used basis. Of course, the one-page-one-entry policy leads to cache invalidation on e.g. scale change. Prefetching always tries to fetch one "row" before the current visisble one and one "row" after, i.e. in single page mode this is +-1 whereas in two-page mode this -2+3 from the current page. There used to be an option to control the amount of prefetching ("prefetch distance"), but it was decided that this is too much emphasis on what is essential a performance hack. Again, I'll think about reintroducing it in the next release.

The real catch here is of course, multi-threaded rendering which will speed up things considerably when it hits Poppler. This improves especially the conceived performance as this feeling of waiting for the pages one-by-one is gone. But as Benjamin indicated, it will take some time until this can be properly incorporated into Poppler.

Revision history for this message
Adam Reichold (adamreichold) said :
#4

Ok, so the next iteration should have the "prefetch distance" setting again, controlling the number of "rows" that are prefetched before and after the one containing the current page. (Working what would be the best thing for the presentation view will probably take a little longer.)

Revision history for this message
Adam Reichold (adamreichold) said :
#5

Ok, the branch "lp:~adamreichold/qpdfview/presentation-prefetch" changes the presentation view to use the same page item class that is used in the main view, hence it will show the same caching behavior as if it were another tab and it will do prefetching according to the main view's settings.

There are still some problems with this as the approach implies that the page item will offer it's full capabilities, i.e. URL links, annotations and forms and it will draw its decoration border and so on... I would probably have to add a locked down "presentation mode" to the page item class. But maybe Alexander has opinion on this as well.

Revision history for this message
Adam Reichold (adamreichold) said :
#6

(Of course, testing this is very much appreciated.)

Revision history for this message
Alexander Volkov (a-volkov) said :
#7

I don't really like this implementation. At first glance it looks like using a sledge-hammer to crack nuts.
Sorry Adam, but I don't have much time now to study it well.

Revision history for this message
Adam Reichold (adamreichold) said :
#8

I can understand the sentiment, but then I did always consider reimplementing rendering and link handling in the presentation view less than optimal. The second question would be what alternative way to implement prefetching and hence caching in the presentation view could be chosen. I suspect that even adding prefetching of just the next page will make a direct implementation in presentation view much more complicated. (At least explicit doubling of scale factor, transformation, render future watcher, image buffer.) Concerning the runtime costs of reusing the page item in a graphics view, I'd say the presentation view being as heavy as "just another tab" would be something I can live with, especially since it would be much to add more features. (E.g. rotation in the presentation view as in the linked branch.)

Revision history for this message
Adam Reichold (adamreichold) said :
#9

(And just to repeat myself, we have all the time in world. No target date is set on version 0.4.)

Revision history for this message
Adam Reichold (adamreichold) said :
#10

To make sure that we be able to make an informed decision on the issue: Carli, can you test the linked branch by building from source?

Revision history for this message
Carli Samuele (carlisamuele) said :
#11

Bit busy at the moment...
I get:

objects/documentview.o: In function `DocumentView::printUsingCUPS(QPrinter*, PrintOptions const&)':
documentview.cpp:(.text+0x23fd): undefined reference to `cupsGetDests'
documentview.cpp:(.text+0x2448): undefined reference to `cupsGetDest'
documentview.cpp:(.text+0x24c8): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x252d): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x258d): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x25ba): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x25df): undefined reference to `cupsAddOption'
objects/documentview.o:documentview.cpp:(.text+0x2607): more undefined references to `cupsAddOption' follow
objects/documentview.o: In function `DocumentView::printUsingCUPS(QPrinter*, PrintOptions const&)':
documentview.cpp:(.text+0x2932): undefined reference to `cupsFreeDests'
documentview.cpp:(.text+0x2942): undefined reference to `cupsFreeOptions'
documentview.cpp:(.text+0x2a09): undefined reference to `cupsPrintFile'
documentview.cpp:(.text+0x2a8c): undefined reference to `cupsLastErrorString'
documentview.cpp:(.text+0x2ba9): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x2bf1): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x2c1a): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x2ca1): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x2cc1): undefined reference to `cupsAddOption'
objects/documentview.o:documentview.cpp:(.text+0x2d38): more undefined references to `cupsAddOption' follow
objects/documentview.o: In function `DocumentView::printUsingCUPS(QPrinter*, PrintOptions const&)':
documentview.cpp:(.text+0x2eb1): undefined reference to `cupsLastErrorString'
collect2: error: ld returned 1 exit status
make[1]: *** [qpdfview] Error 1
make[1]: Leaving directory `/tmp/qpdf/qpdf'
make: *** [sub-qpdfview-application-pro-make_default-ordered] Error 2

Fast idea to overcome that?

Thanks!
Samuele

Revision history for this message
Adam Reichold (adamreichold) said :
#12

The most simple way would be to pass "CONFIG += without_cups" to qmake, i.e. 'qmake "CONFIG += without_cups"'. (There is no rush about this, it was rather the question of whether you would be willing to do it in principle.)

Revision history for this message
Carli Samuele (carlisamuele) said :
#13

Yup, that's the first thing i tried, but seems to have no effect.
Busy period, but i'm of course willing to help as much as i can!

Thank you very much anyway!
Sam

Revision history for this message
Adam Reichold (adamreichold) said :
#14

Sorry that is my fault: I recently refactored printing using Qt and CUPS into separate helper methods and forget to properly #ifdef the CUPS helper. Should be fixed in trunk revision 929.

Revision history for this message
Adam Reichold (adamreichold) said :
#15

And now I remembered that I would have to merge those changes into the presentation-prefetch branch as well... Sorry, been a long day.

Revision history for this message
Adam Reichold (adamreichold) said :
#16

Concerning parallel rendering of pages: This was just comitted to Poppler's master and can be tested using the branch at [1]. (Library paths have to be adjusted manually in the project files.)

[1] lp:~adamreichold/qpdfview/poppler-threading

Revision history for this message
Adam Reichold (adamreichold) said :
#17

Hello again,

Since the initial problem needs to be solved and we can always improve the (admittedly quite heavy handed) implementation later on, I merged this after some consideration made some further adjustments to prefetching. As this is now part of trunk, testing should be much easier using the usual packages.

Best regards, Adam.

Revision history for this message
Adam Reichold (adamreichold) said :
#18

Hello Carli,

Were you able to test the branch or later trunk with those changes committed? Does the prefetching now work satisfactory in the presentation view?

Best regards, Adam.

Revision history for this message
Carli Samuele (carlisamuele) said :
#19

Hello!

Sorry for the late reply...

I still cannot get over the cups dependencies:

$qmake CONFIG+=without_cups qpdfview.pro
$ make

[...]

g++ -m64 -Wl,-O1 -o qpdfview objects/model.o objects/pageitem.o objects/searchthread.o objects/presentationview.o objects/documentview.o objects/printoptionswidget.o objects/miscellaneous.o objects/settings.o objects/settingsdialog.o objects/recentlyusedmenu.o objects/bookmarkmenu.o objects/mainwindow.o objects/main.o objects/synctex_parser.o objects/synctex_parser_utils.o objects/signalhandler.o objects/moc_pageitem.o objects/moc_searchthread.o objects/moc_presentationview.o objects/moc_documentview.o objects/moc_printoptionswidget.o objects/moc_miscellaneous.o objects/moc_settings.o objects/moc_settingsdialog.o objects/moc_recentlyusedmenu.o objects/moc_bookmarkmenu.o objects/moc_mainwindow.o objects/moc_signalhandler.o objects/qrc_qpdfview.o -L/usr/lib/x86_64-linux-gnu -lz -lmagic -lQtDBus -lQtSvg -lQtSql -lQtGui -lQtCore -lpthread
objects/documentview.o: In function `DocumentView::printUsingCUPS(QPrinter*, PrintOptions const&)':
documentview.cpp:(.text+0x226d): undefined reference to `cupsGetDests'
documentview.cpp:(.text+0x22b8): undefined reference to `cupsGetDest'
documentview.cpp:(.text+0x2338): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x239d): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x23fd): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x242a): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x244f): undefined reference to `cupsAddOption'
objects/documentview.o:documentview.cpp:(.text+0x2477): more undefined references to `cupsAddOption' follow
objects/documentview.o: In function `DocumentView::printUsingCUPS(QPrinter*, PrintOptions const&)':
documentview.cpp:(.text+0x27a2): undefined reference to `cupsFreeDests'
documentview.cpp:(.text+0x27b2): undefined reference to `cupsFreeOptions'
documentview.cpp:(.text+0x2879): undefined reference to `cupsPrintFile'
documentview.cpp:(.text+0x28fc): undefined reference to `cupsLastErrorString'
documentview.cpp:(.text+0x2a19): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x2a61): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x2a8a): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x2b11): undefined reference to `cupsAddOption'
documentview.cpp:(.text+0x2b31): undefined reference to `cupsAddOption'
objects/documentview.o:documentview.cpp:(.text+0x2ba8): more undefined references to `cupsAddOption' follow
objects/documentview.o: In function `DocumentView::printUsingCUPS(QPrinter*, PrintOptions const&)':
documentview.cpp:(.text+0x2d21): undefined reference to `cupsLastErrorString'
collect2: error: ld returned 1 exit status
make[1]: *** [qpdfview] Error 1
make[1]: Leaving directory `/tmp/qpdfview/qpdfview'
make: *** [sub-qpdfview-application-pro-make_default-ordered] Error 2

any idea?

Thanks!

Sam

Revision history for this message
Adam Reichold (adamreichold) said :
#20

Hhhmmm, actually, I have no idea... The current source from trunk using the "without_cups" option builds fine here...

The g++ command-line to compile "documentview.cpp" might be helpful to see whether the definition "-DWITH_CUPS" is passed to the compiler or omitted.

Other than that, more information on the operating system / distribution you use might also be useful. Did you try to install the CUPS development headers and libraries (maybe just temporarily)?

Revision history for this message
Adam Reichold (adamreichold) said :
#21

I am not sure this does anything for you, but there are daily builds from trunk for Ubuntu and derivates [1] as well as OpenSUSE and Fedora [2] available. (As of comment #17, prefetching for the presentation view is in trunk.)

[1] https://code.launchpad.net/~adamreichold/+recipe/qpdfview-dailydeb

[2] https://build.opensuse.org/package/show?package=qpdfview&project=X11%3AQtDesktop%3Atrunk

Revision history for this message
Carli Samuele (carlisamuele) said :
#22

Hello again!

I'm on debian sid, with all the dependencies i could track down installed (since the beginnig).
Not sure what something changed, but I could compile today's trunk.

Seems to work fine, much faster then before.

Thank you very much!
Sam

Revision history for this message
Karl-Heinz Zimmer (khzimmer) said :
#23

Hi guys,

not sure if anyone else will stumble over the unresolved externals of cups issue, but this is what I just found:

The problem occurs if you had added some missing libs one by one (just as you notice they are missing during repeated attempts of running make) because you did not read README carefully enough before starting.

:-)

So let us assume you now HAVE installed all of the missing development libs, then
this is how to continue then, just remove the old stuff and restart like this:

make distclean
lrelease qpdfview.pro
qmake qpdfview.pro
make && sudo make install

Cheers
Karl-Heinz

Revision history for this message
arthropodzo (felipe-spam-spam) said :
#24

@khzimmer
Thank you so much, I was mindlessly using

make clean

and I simply didn't think of checking all the makefile targets. Everything compiles just fine after distclean

Revision history for this message
Alexey S (ostrokach) said :
#25

@khzimmer Thank you! I followed your instructions and it fixed the problem.