LINUX.ORG.RU

Помогите посадить okular на диету!

 ,


0

1

Доброго времени суток.

Сегодня совершенно случайно заметил, что okular жрет 16 гигов оперативки, в этот момент была открыта pdf'ка на 40 мегабайт. Стало интересно, захотелось понять причину. Протестировал его на нескольких pdf/djvu разных размеров. Проблема проявлялась во всех случаях. В результате было замечено, что аппетит у очкарика зависит от размера файла, т.е. на небольших экземплярах (2 - 5 мб) кушает в пределах 2 - 3 гб оперативки, на солидных книжищах (~1000 страниц, ~50 мб) сжирает в пределах 15 - 20 гб оперативки.

Не могу сказать, когда это началось, так как внешне на стабильность системы это никак не влияло. Машинка у меня на вырост, 32 кг памяти, а своп хоть и включен, но ни разу не было ситуации (не замечал этого), когда бы он использовался, поэтому и тормозов не было замечено.

Пришла в голову мысль поставить valgrind и посмотреть, что он скажет. Не знаю точно, что нужно делать, так как раньше не доводилось его не юзать, да и вообще нет опыта работы с профайлерами. Просматривая маны, бросилось в глаза два модуля, memcheck и massif. Вот результаты:

valgrind --leak-check=full okular

После запуска okular'а, был открыт pdf файл на 4 мб.

Выхлоп - http://pastebin.com/raw.php?i=20m3TQ2E

Взято из top:

2542776 1,998g 52848 S   0,0  6,4   0:06.62 okular

Далее был запущен massif и открыт тот же файл на 4 мб:

valgrind --tool=massif okular

ms_print massif.out.2478

Верхушка лога:

--------------------------------------------------------------------------------
Command:            okular
Massif arguments:   (none)
ms_print arguments: massif.out.2478
--------------------------------------------------------------------------------


    GB
1.919^                                                                       #
     |                                                                     @@#
     |                                                                 @@:@@@#
     |                                                              @@@@@:@@@#
     |                                                          ::@:@ @@@:@@@#
     |                                                       ::@: @:@ @@@:@@@#
     |                                                  @@@::::@: @:@ @@@:@@@#
     |                                               ::@@ @: ::@: @:@ @@@:@@@#
     |                                            ::@::@@ @: ::@: @:@ @@@:@@@#
     |                                         @::: @::@@ @: ::@: @:@ @@@:@@@#
     |                                     :@::@::: @::@@ @: ::@: @:@ @@@:@@@#
     |                                ::@:::@: @::: @::@@ @: ::@: @:@ @@@:@@@#
     |                              @:: @: :@: @::: @::@@ @: ::@: @:@ @@@:@@@#
     |                          ::::@:: @: :@: @::: @::@@ @: ::@: @:@ @@@:@@@#
     |                      @@::::: @:: @: :@: @::: @::@@ @: ::@: @:@ @@@:@@@#
     |                  ::@:@ : ::: @:: @: :@: @::: @::@@ @: ::@: @:@ @@@:@@@#
     |                 :: @:@ : ::: @:: @: :@: @::: @::@@ @: ::@: @:@ @@@:@@@#
     |            ::::::: @:@ : ::: @:: @: :@: @::: @::@@ @: ::@: @:@ @@@:@@@#
     |        @:::: :: :: @:@ : ::: @:: @: :@: @::: @::@@ @: ::@: @:@ @@@:@@@#
     |    ::@@@:: : :: :: @:@ : ::: @:: @: :@: @::: @::@@ @: ::@: @:@ @@@:@@@#
   0 +----------------------------------------------------------------------->Gi
     0                                                                   42.85

Обжористый стек вызовов (взято из начала лога), тут он кушает всего 150 метров:

99.31% (156,626,353B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->95.06% (149,931,100B) 0x6A4D60A: QImageData::create(QSize const&, QImage::Format, int) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| ->94.80% (149,517,876B) 0x6A4D75B: QImage::QImage(int, int, QImage::Format) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | ->94.26% (148,661,288B) 0x6A4E9A1: QImage::copy(QRect const&) const (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | ->78.71% (124,136,496B) 0x6A4F913: QImage::detach() (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | ->78.71% (124,136,496B) 0x6A750C5: QRasterPixmapData::createPixmapForImage(QImage&, QFlags<Qt::ImageConversionFlag>, bool) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | | ->78.71% (124,136,496B) 0x6A75130: QRasterPixmapData::fromImage(QImage const&, QFlags<Qt::ImageConversionFlag>) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |   ->78.71% (124,136,496B) 0x6A66ED0: QPixmap::fromImage(QImage const&, QFlags<Qt::ImageConversionFlag>) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |     ->78.71% (124,136,496B) 0x182BD157: ??? (in /usr/lib64/libokularcore.so.5.0.0)
| | | | |       ->78.71% (124,136,496B) 0x64828BC: QObject::event(QEvent*) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |         ->78.71% (124,136,496B) 0x699935A: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |           ->78.71% (124,136,496B) 0x699FACB: QApplication::notify(QObject*, QEvent*) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |             ->78.71% (124,136,496B) 0x5771568: KApplication::notify(QObject*, QEvent*) (in /usr/lib64/libkdeui.so.5.14.8)
| | | | |               ->78.71% (124,136,496B) 0x646A26B: QCoreApplication::notifyInternal(QObject*, QEvent*) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                 ->78.71% (124,136,496B) 0x646D488: QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                   ->78.71% (124,136,496B) 0x649818C: ??? (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                     ->78.71% (124,136,496B) 0xB2FC552: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.4200.2)
| | | | |                       ->78.71% (124,136,496B) 0xB2FC796: ??? (in /usr/lib64/libglib-2.0.so.0.4200.2)
| | | | |                         ->78.71% (124,136,496B) 0xB2FC83A: g_main_context_iteration (in /usr/lib64/libglib-2.0.so.0.4200.2)
| | | | |                           ->78.71% (124,136,496B) 0x649795C: QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                             ->78.71% (124,136,496B) 0x6A37674: ??? (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |                               ->78.71% (124,136,496B) 0x6468DFD: QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                                 ->78.71% (124,136,496B) 0x64690F3: QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                                   ->78.71% (124,136,496B) 0x646E557: QCoreApplication::exec() (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                                     ->78.71% (124,136,496B) 0x409BDE: ??? (in /usr/bin/okular)
| | | | |                                       ->78.71% (124,136,496B) 0x7788AA3: (below main) (in /lib64/libc-2.20.so)

Этот же стек (в конце лога), но теперь он кушает 2 гигабайта:

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 56 46,009,662,363    2,060,416,776    2,057,966,717     2,450,059            0
99.88% (2,057,966,717B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->97.66% (2,012,172,328B) 0x6A4D60A: QImageData::create(QSize const&, QImage::Format, int) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| ->97.65% (2,011,902,528B) 0x6A4D75B: QImage::QImage(int, int, QImage::Format) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | ->97.62% (2,011,368,392B) 0x6A4E9A1: QImage::copy(QRect const&) const (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | ->96.43% (1,986,843,600B) 0x6A4F913: QImage::detach() (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | ->96.43% (1,986,843,600B) 0x6A750C5: QRasterPixmapData::createPixmapForImage(QImage&, QFlags<Qt::ImageConversionFlag>, bool) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | | ->96.43% (1,986,843,600B) 0x6A75130: QRasterPixmapData::fromImage(QImage const&, QFlags<Qt::ImageConversionFlag>) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |   ->96.43% (1,986,843,600B) 0x6A66ED0: QPixmap::fromImage(QImage const&, QFlags<Qt::ImageConversionFlag>) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |     ->96.43% (1,986,843,600B) 0x182BD157: ??? (in /usr/lib64/libokularcore.so.5.0.0)
| | | | |       ->96.43% (1,986,843,600B) 0x64828BC: QObject::event(QEvent*) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |         ->96.43% (1,986,843,600B) 0x699935A: QApplicationPrivate::notify_helper(QObject*, QEvent*) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |           ->96.43% (1,986,843,600B) 0x699FACB: QApplication::notify(QObject*, QEvent*) (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |             ->96.43% (1,986,843,600B) 0x5771568: KApplication::notify(QObject*, QEvent*) (in /usr/lib64/libkdeui.so.5.14.8)
| | | | |               ->96.43% (1,986,843,600B) 0x646A26B: QCoreApplication::notifyInternal(QObject*, QEvent*) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                 ->96.43% (1,986,843,600B) 0x646D488: QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                   ->96.43% (1,986,843,600B) 0x649818C: ??? (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                     ->96.43% (1,986,843,600B) 0xB2FC552: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.4200.2)
| | | | |                       ->96.43% (1,986,843,600B) 0xB2FC796: ??? (in /usr/lib64/libglib-2.0.so.0.4200.2)
| | | | |                         ->96.43% (1,986,843,600B) 0xB2FC83A: g_main_context_iteration (in /usr/lib64/libglib-2.0.so.0.4200.2)
| | | | |                           ->96.43% (1,986,843,600B) 0x649795C: QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                             ->96.43% (1,986,843,600B) 0x6A37674: ??? (in /usr/lib64/qt4/libQtGui.so.4.8.6)
| | | | |                               ->96.43% (1,986,843,600B) 0x6468DFD: QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                                 ->96.43% (1,986,843,600B) 0x64690F3: QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                                   ->96.43% (1,986,843,600B) 0x646E557: QCoreApplication::exec() (in /usr/lib64/qt4/libQtCore.so.4.8.6)
| | | | |                                     ->96.43% (1,986,843,600B) 0x409BDE: ??? (in /usr/bin/okular)
| | | | |                                       ->96.43% (1,986,843,600B) 0x7788AA3: (below main) (in /lib64/libc-2.20.so)

Полный лог massif + ms_print - http://pastebin.com/raw.php?i=irEudVpd

gentoo, qt 4.8.6-r1, poppler 0.32.0, okular 4.14.3

Баг или фича?

Он использует до 50% памяти, установленной в системе.

Вкладка перформанс в настройках.

Под отладчиком потребление памяти выше.

wakuwaku ★★★★ ()
Последнее исправление: wakuwaku (всего исправлений: 2)

у меня окуляр ел максимум ~800 метров (в системе 8 Гб), и то это на 5 открытых pdf по несколько десятков мегабайт каждый

anonymous ()
Ответ на: комментарий от wakuwaku

Нашел:

Загружать и держать всё в памяти. Использовать предварительную загрузку всех страниц. Будет использована вся свободная память, но не более 50% от общего объёма оперативной памяти.

Мне не пришло в голову лезть в настройки... Когда увидел потребление 16 гигов памяти, первая и единственная мысль - утечка.

Таки фича.

Nietzsche ()

к чертям okular, используй zathura или qpdfview.

kep ()

Фича, конечно же. У каждой кодае-поделки такая фича.

entefeed ☆☆☆ ()
Ответ на: комментарий от kep

qpdfview гуд, хотя на дефолтных настройках «дергаются» страницы при прокрутке, т.е. подгружаются на лету из-за кэша 32 мб, а чтобы было плавненько, надо включать предзагрузку и увеличивать кэш до 1 - 2 гигов (для 40 метрового pdf), тогда все плавненько прокручивается.

В окуляре тоже можно регулировать потребление памяти, но тут нравится то, что четче обозначены границы потребления.

Все-таки 16 гигабайт памяти для книги - перебор. И это хорошо, что у меня всего 32 гигабайта, я подозреваю, что оно с легкостью сожрало бы в разы больше, будь у меня пару лишних планок дидиэр.

Nietzsche ()

для твоего же блага старается

ionanahin ★★★ ()
Ответ на: комментарий от ionanahin

Как по мне, слишком уж упорно он это делает. Не удивлюсь, если разработчики решат переписать всё на жабе, будет органично смотреться.

Nietzsche ()
Ответ на: комментарий от Nietzsche

Чувак есть фича, она включена и работает. Что тебе не нравится? В случае с потреблением рамы лучше считать относительное потребление, а не абсолютное. Ты же покупал 32 GB не для того, чтобы у тебя 28 из них всегда были пустыми?

yurikoles ★★★ ()
Ответ на: комментарий от yurikoles

Когда стало понятно, что это фича - все вопросы снялись. Никаких проблем с производительностью системы я не замечал, но при определенных условиях эти проблемы могли бы вылезти. Зато теперь я нашел более подходящий софт для своих нужд, чего и всем желаю.

Nietzsche ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.