очень медленный запуск приложения на python

Landstreicher

Пытаюсь написать простенькое GUI на Python с использованием KDE bindings for python.
Все работает правильно, но грузится ужааасно мееедленно.
Выкинул из программы все содержание:

!/usr/bin/env python
import sys
import kdecore
import kio

kdecore.KCmdLineArgs.init(sys.argv, 'ABC', None, None)
app = kdecore.KApplication
Специально проверял - процессор полностью свободен, памяти навалом, все файлы в кэше (делается много предварительных запусков). Результат всегда примерно одинаков (колебания около пары процентов):

[laputa ~]$ /usr/bin/time python 1.py
0.69user 0.05system 0:00.76elapsed 98%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+5651minor)pagefaults 0swaps
Тоже самое на C++:

#include <kapp.h>
#include <kcmdlineargs.h>

int main( int argc, char **argv )
{
KCmdLineArgs::init(argc, argv, "ABC", "ABC", "ABC", "0.01");
KApplication a;
KCmdLineArgs *args = KCmdLineArgs::parsedArgs;
return 0;
}
[laputa ~]$ /usr/bin/time ./2
0.15user 0.04system 0:00.22elapsed 91%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+2109minor)pagefaults 0swaps

То есть просто инициализация объекта KApplication занимает в 69/15 = 4.6 раз больше времени!
Чем это можно объяснить? Мне всегда казалось что большую часть временти в таких программах отнимают сами процедуры, написанные на языке C++. Ведь по сути дела никакого кода на Python не выполняется! Чего же там может так тормозить?
Как можно ускорить запуск? Может показаться что 0.69 это фигня, но само приложение в реальных условиях грузится долго - до 5 сек. В то же время какой-нибудь там konqueror грузится мгновенно. Если ускорить никак не удастся, я скорее перейду на другой язык для которого есть kde bindings. Какие есть альтернативы (помимо очевидного C++)?

Julie16

Это все из-за динамической загрузки библиотек. Ты же не можешь слинковать python с kdelibs Вот он и ресолвит нужные имена в рантайме. Ну и плюс конечно еще одна прослойка в виде С кода.

Julie16

PS: и дело совсем не в KApplication. После того как библиотека слинковалась, тормозов не будет.

Landstreicher

Насколько я понимаю тут нужно отрезолвить 3 динамических метода: KCmdLineArgs.init, конструктор KApplication, деструктор KApplication.
Неужели можно резолвить 3 метода в течение 0.69-0.15 = 0.54 секунд?
Кроме того, модули уже скомпилены:

[laputa ~]$ ldd /usr/lib/python2.3/site-packages/kdecore.so
libkdecore.so.4 => /usr/lib/libkdecore.so.4 (0xb7b7c000)
libqt-mt.so.3 => /usr/lib/libqt-mt.so.3 (0xb748f000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0xb7481000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0xb73ba000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0xb73ab000)
libstdc++.so.5 => /usr/lib/libstdc++.so.5 (0xb72f1000)
.....
То есть все точно так же как и в случае C++.
IMHO такое объяснение совершенно не состоятельно.

Julie16

Е-мое, а как ты думаешь эти модули подгружаются в питон? Святым духом? Они резолвятся в рантайме. Тем более, как питон скажет линкеру что ему нужны только эти символы? Нет, он все резолвит.

Landstreicher

не понял. можно более подробно в чем отличие от C++? в нем ведь тоже libkdecore.so.4 подгружается динамически и резолвятся те же самые 3 метода.

Julie16

Да, но библиотека уже слинкована с программой. Там указаны какие символы используются, какие - нет. +prelink опять же. А в этом случае все не так. Мы априори не знаем что нам понадобится.

Landstreicher

> Е-мое, а как ты думаешь эти модули подгружаются в питон? Святым духом?
Не знаю. Расскажи.
> Они резолвятся в рантайме.
Также как и В C++ они тоже резолвятся по мере обращения. То есть если я использовал три метода, то только они и срезолвятся. Не вижу причин, почему резолв имен в питоне должен быть медленнее чем в случае обычных c++-программ.

Landstreicher

я не использую prelink, поэтому за счет его тоже не получается ничего объяснить

Landstreicher

я правильно понимаю, что ты хочешь сказачть, что резолвятся все символы libskdecore.so.4? Если да - то почему? Насколько мне известно, по дефолту линкер ld-linux.so.2 использует lazy binding.

Julie16

>Не знаю. Расскажи.
dlopen && dlsym. Я объясняю. Питон не знает какие символы ему понадобятся из этих библиотек-заглушек. Так как он не обрабатывает текст своей программы. Он - интерпретатор. Он не может сказать какие функции будут использованы а какие - нет. Поэтому он загружает библиотеки - заглушки целиком. А они целиком тащат kdelibs.
>Также как и В C++ они тоже резолвятся по мере обращения
Нет. Они резолвятся во время загрузки программы. А так как мы знаем какие символы использованы, то нет проблем.

Julie16

А вообще, сделай export LD_DEBUG=statistics
И погоняй питоновскую прогу и С++ эквивалент.

Landstreicher

> Поэтому он загружаеи библиотеки - заглушки целиком. А они целиком тащат kdelibs.
Неверно. В дефолтной конфигурации символы резолвятся в момент первого обращения.
man 3 dlopen

The value of flag can be either RTLD_LAZY or RTLD_NOW. When RTLD_NOW is specified, or the
environment variable LD_BIND_NOW is set to a non-empty string, all undefined symbols in the
library are resolved before dlopen returns. If this cannot be done, an error is returned.
Otherwise binding is lazy: symbol values are first resolved when needed.

> Нет. Они резолвятся во время загрузки программы.
Откуда такая инфа? Ссылку плз.

Julie16

1) Ок. kdelibs в лучшем случае резолвятся позже. Но заглушки резолвятся сразу же и целиком. С этим ты уже не споришь? А ин ровно столько же сколько и в kdelibs.
2) ? Тебе интересен процесс загрузки программ? Ну вот тут есть: ftp://people.redhat.com/jakub/prelink/prelink.pdf

Julie16

>Неверно. В дефолтной конфигурации символы резолвятся в момент первого обращения.
Неверно. Зависимые символы резолвятся потом. Тот символ который ты запросил, резолвится сразу.

Landstreicher

Почему заглушки резолвятся все? Тот же самый механизм --- заглушки резолвятся по мере обращения. В чем разница с kdelibs?

vall

а ты импорти из модулей только те имена что тебе нужны, может поможет.

Julie16

Потому что python загружает библиотеки с RTLD_NOW. И почему это должен был искать я?
PS: попробуй сделать так:
#! /usr/bin/python
import sys
sys.setdlopenflags(1) //или 0
import pyqt blablabla

Landstreicher

> Потому что python загружает библиотеки с RTLD_NOW. И почему это должен был искать я?
Во! Это уже информация по делу, многое проясняет. Однако согласись - RTLD_NOW мало кто явно указывает, если этого не знать, предположить это сложно.
Есть какие-нибудь идеи зачем так сделано?
> sys.setdlopenflags(1) //или 0
Пробовал. 1 = RTLD_LAZY, 0 не дают. Результат - небольшое ускорение. Вместо 0.69 теперь 0.42. Это уже лучше, однако все равно много. Нужны какие-то идеи для дальнейшего улучшения.
Кто-нибудь знает, какая ситуация с kde binding для perl, ruby, других скриптовых языков? Там такие же тормоза или лучше?
Оставить комментарий
Имя или ник:
Комментарий: