Советы по производительности

вопросы по созданию программ с использованием возможностей библиотеки PHPQt5

Модератор: ArtMares

rinart73
Аватара пользователя
 
Сообщения: 36
Skype: art7emw
Поблагодарили: 2 раза
Раз уж PHP пришел на сторону клиента, да не как раньше, а с GUI, пора задуматься о производительности.
В этой теме будут собираться советы и хаки по оптимизации скорости работы программы.
Некоторые из них могут показаться для хорошо знающих программирование и php банальными, другие нет. (Другие могут показаться ненормальными)
Хочу отметить, что указанные данные справедливы для PQEngine 0.5.1 (PHP 7.0.4). Т.е., по сути, данные советы являются верными для текущей версии. В будущем ситуация может измениться.

Несколько советов от меня:

  1. and, or vs &&, ||
  2. Хотя and и or более понятны при чтении, заменив их на && и ||, можно получить некоторый выигрыш в производительности.Учтите, что эти операторы имеют отличия в приоритете выполнения.Тесты показали увеличение производительности на 15% - 250% (в зависимости от типов)

  3. $i++, $i-- vs ++$i, --$i
  4. Здесь ситуация более спорная и в первую очередь надо уделить внимание разному стилю работы ++$i и $i++:
    phpqt Код:
    $a = 0;
    $b = 0;
    $c = 0;
    $d = 0;

    $a += $c++; //0
    $b += ++$d; //1

    Но в случае, когда от замены $i-- на --$i не ломается логика программы, советую использовать второй вариант.
    Выигрыш от использования составляет около 60%.

  5. Qt: методы vs свойства
  6. Многие параметры Qt виджета можно задать(и получить) либо обращением к свойству, либо вызовом метода:
    phpqt Код:
    $title = $mainWindow->windowTitle();
    $mainWindow->setGeometry($x, $y, $width, $height);

    $title = $mainWindow->windowTitle;
    $mainWindow->x = $x;
    $mainWindow->y = $y;
    $mainWindow->width = $width;
    $mainWindow->height = $height;

    И вариант с использованием свойств всегда быстрее. Даже когда, как в примере выше, используется обращение к 4 свойствам вместо вызова одного метода.
    Здесь играет роль то, что на вызов функции и выход из нее также тратится время. +, вероятно, эти методы просто обращаются к тем же переменным(?).
    Однако стоит использовать методы, в том случае, когда виджет, с которым вы работаете, в данный момент виден пользователю (и при этом метод принимает более 1 аргумента). Иначе окно будет перемещаться по экрану сначала вправо(x), а уже потом на нужную позицию.
    В примере выше 4 свойства x, y, width, height быстрее setGeometry на ~440%.
Почетный страдалец фигней
Пилю load_ui_file :good2:

WxMaper
Аватара пользователя
Администратор
 
Сообщения: 92
Благодарил (а): 8 раз
Поблагодарили: 4 раза
rinart73 писал:В примере выше 4 свойства x, y, width, height быстрее setGeometry на ~440%.

Ты сам замерял производительность? Если да, то хотелось бы увидеть графики =)
Вообще это было известно, но "вещественного" подтверждения этому не было, т.к. я полагался лишь на анализ вызовов.

Да, действительно, обращение к свойствам работает в разы быстрее, чем обращение к методам. Это связано с тем, что вызов метода, помимо конвертации параметров, сопровождается поиском "удачного" вызова, так как метод может быть перегруженным.
Движок перебирает подходящие методы и пытается конвертировать переданные параметры во входные параметры метода. Если конвертация прошла удачно, то движок пытается вызвать метод. Если метод вызвался удачно, то перебор прерывается.

Это не самая хорошая идея и не самая лучшая её реализация, но по другому я не придумал перебор перегруженных методов :nea:
Самый большой минус такого подхода в том, что движок может случайно вызвать не тот метод, когда у него получится удачно конвертировать все входные параметры. Пока такое отчётливо наблюдается только с конструктором объекта QSettings. Там перегрузка конструктора позволяет создать объект аж одиннадцатью методами (если не ошибаюсь).

Установка свойства же проходит всего в 2 этапа: конвертация типов и установка свойства через специальный метод Qt.
diag.png

rinart73
Аватара пользователя
 
Сообщения: 36
Skype: art7emw
Поблагодарили: 2 раза
WxMaper писал:Ты сам замерял производительность?

Да, 440% не сами собой появились))
Графики скоро будут.

Надо что-то придумать, с вызовом методов, т.к. полно методов, которым не подберешь свойство(-а)-аналог(-и). Узкое место получается... К сожалению, беглое гугление по теме заставляет волосы встать дыбом, но если что найду - напишу.
Почетный страдалец фигней
Пилю load_ui_file :good2:

zazaka
Аватара пользователя
Ответственный глюкогенератор
 
Сообщения: 98
Поблагодарили: 2 раза
спс за инфу)  очень полезно!
Унабле то лоад дынамиц либрары

rinart73
Аватара пользователя
 
Сообщения: 36
Skype: art7emw
Поблагодарили: 2 раза
Графика все-еще нет, по я прогнал тесты для темплейта MainWindow с setGeometry и ее заменой.
Было два прогона: до $mainWindow-show() и после.
Есть уточнения(потом внесу в шапку):
  1. Однозначно лучше использовать св-ва для получения значений, а также для замены методов, принимающих один аргумент.

  2. При наличии более 1 аргумента, следует учесть, видимо ли(show) в данный момент окно с виджетом:

  3. Да - использовать методы для установки параметров (если метод принимает более 1 аргумента).

    Нет - использовать свойства.


При использовании свойств для установки значений, приходится перерисовывать окно в (количество_свойств) раз чаще.

Итак, setGeometry vs св-ва. Код вида:
phpqt Код:
for($e = 0; $e < 100; $e++) {
  for($f = 10; $f < 100; $f++) {
    $mainWindow->setGeometry($e,$e,$f,$f); //Дин. значение
    $mainWindow->setGeometry(0,0,100,100); //фиксированное значение
  }
}

(И, соответственно, то же, но с использованием свойств).

РЕЗУЛЬТАТЫ (setGeometry (vs) x,y,width,height):
До show(): 3717 мсек (vs) 771 мсек
После show(): 22878 мсек (vs) 50999 мсек

UPD:
РЕЗУЛЬТАТЫ (setWindowTitle (vs) windowTitle):
До show(): 2260 мсек (vs) 454 мсек
После show(): 15667 мсек (vs) 14634 мсек
Почетный страдалец фигней
Пилю load_ui_file :good2:

WxMaper
Аватара пользователя
Администратор
 
Сообщения: 92
Благодарил (а): 8 раз
Поблагодарили: 4 раза
rinart73 писал:После show(): 22878 мсек (vs) 50999 мсек

:shok: таки выходит, что перерисовка виджета занимает больше времени, чем сама передача вызова из пыха в Qt. Печальный факт, однако :sad:

ArtMares
Аватара пользователя
 
Сообщения: 72
Откуда: Москва
Благодарил (а): 4 раза
Поблагодарили: 5 раз
Поделюсь своими заметкими на счет свойств.

Сталкивался неоднократно и в итоге стал использовать в основном только методы.

Как правильно заметил rinart73 необходимо обратить внимание на то видим ли объект или нет. При чем это касается не только самого окна но и всех его дочерних элементов.

Было замечено что даже у таких элементов как QLineEdit лучше использовать методы для получения и задания значения. Так как в противном случае (я не знаю с чем это связано, не стал разбираться) получаем из свойства пустую строку.

Скажу сразу что такие проблемы возникают только в тех случаях когда приложение становится увесистым (имеет большое количество дочерних элементов, множество отдельных окон), так же такие проблемы возникают когда компьютер на котором запущено приложение очень сильно загружен (тестировал на работе на компьютерах пользователей которые вечно жалаются что у них все тормозит)

По этому лично мое мнение для стабильной работы приложения используйте методы а не свойства.
Свойства используейте только когда проводите инициализацию приложения и всех его графических элементов.
PQStudio Development Progress: 75%
Version: 0.2

WxMaper
Аватара пользователя
Администратор
 
Сообщения: 92
Благодарил (а): 8 раз
Поблагодарили: 4 раза
ArtMares писал:Было замечено что даже у таких элементов как QLineEdit лучше использовать методы для получения и задания значения. Так как в противном случае (я не знаю с чем это связано, не стал разбираться) получаем из свойства пустую строку.

Это и в версии 0.5.1 с установленным патчем наблюдается? Потому что в патче было исправление как раз по этой части.

ArtMares
Аватара пользователя
 
Сообщения: 72
Откуда: Москва
Благодарил (а): 4 раза
Поблагодарили: 5 раз
WxMaper писал:Это и в версии 0.5.1 с установленным патчем наблюдается? Потому что в патче было исправление как раз по этой части.


Да, вот буквально вчера пришлось старый кусок кода заменить так как отвалился поиск в приложении.
Так же пришлось переделать обработку событий для закрытия окна приложения
phpqt Код:
public function eventListener($sender, $event) {
    /** Делаем проверку на тип события */
    switch($event->type) {
        case QEvent::Close:
            /** При закрытии окна запоминаем его состояние */
            $this->storage->settings->setValue('windowState', $sender->windowState());
            break;
    }
}

Пришлось заменить $event->type на $event->type()
Я конечно не делал замеры на время выполнения, так как для меня более важно стабильность работы
PQStudio Development Progress: 75%
Version: 0.2

WxMaper
Аватара пользователя
Администратор
 
Сообщения: 92
Благодарил (а): 8 раз
Поблагодарили: 4 раза
этот event... я его как раз перед 0.5.1 заменил с "псевдо-класса" на класс из расширения. И конечно же забыл добавить там чтение свойства, будет исправлено.

п.с. раньше QEvent не существовал, сейчас его можно создавать как объект (через new), но передавать пока нельзя. Планируется добавить возможность генерации событий.

rinart73
Аватара пользователя
 
Сообщения: 36
Skype: art7emw
Поблагодарили: 2 раза
WxMaper писал::shok: таки выходит, что перерисовка виджета занимает больше времени, чем сама передача вызова из пыха в Qt. Печальный факт, однако :sad:


Стоит отметить, что у меня медленная Intel Graphics. Когда окно показано, на результаты частой смены параметров уже начинает влиять и видеокарта.

Причем, учитывая описание того, как вызывается метод, я все-же в недоумении.
Что у setGeometry, что у setWindowsTitle разница в 4.8 - 4.9 раз.
У setWindowsTitle нет перегрузок, а процесс все-равно медленный.
Почетный страдалец фигней
Пилю load_ui_file :good2:

ArtMares
Аватара пользователя
 
Сообщения: 72
Откуда: Москва
Благодарил (а): 4 раза
Поблагодарили: 5 раз
rinart73 писал:Стоит отметить, что у меня медленная Intel Graphics. Когда окно показано, на результаты частой смены параметров уже начинает влиять и видеокарта.

У меня на работе у пользователей вообще стоят печатные машинки, только с интергированным видео в процессор.

Да иногда конечно замечаешь что стандартный прогресс бар подтормаживает при отображении анимации, но такое возникает и в моменты когда устанавливаешь программу. Да конечно быстродействие это достаточно критичный фактор, но если при этом у приложения не будет стабильной работы то в моем случае пользоватли не захотят использовать мой софт так сказать.

Я думаю получится как нибудь стабилизировать и быстродействие и стабильность работы, но не раньше чем в следующих обновлениях движка.
А сейчас учитывай при разработке приложения что чем более функиональным оно будет тем более медлее оно будет работать на слабых компьютерах


Ту же самую PQStudio я вообще разрабатываю используя виртуальную машину. Студия в ней в разы медлее запускается, но это все в полне вероятно так как виртуалке выбелен только один процессор и 1Гб оперативки. Тут как бы сам понимаешь что это вполне зависимые вещи. Чем слабее компьютер тем меблее на нем работает все.
PQStudio Development Progress: 75%
Version: 0.2

rinart73
Аватара пользователя
 
Сообщения: 36
Skype: art7emw
Поблагодарили: 2 раза
ArtMares писал:не будет стабильной работы

А можно, пожалуйста, отписаться в раздел багов, какие именно св-ва у каких виджетов пришлось заменить методами?
Почетный страдалец фигней
Пилю load_ui_file :good2:

WxMaper
Аватара пользователя
Администратор
 
Сообщения: 92
Благодарил (а): 8 раз
Поблагодарили: 4 раза
rinart73 писал:Причем, учитывая описание того, как вызывается метод, я все-же в недоумении

Я описал процесс достаточно утрированно. Чтобы увидеть весь путь от вызова метода до его исполнения достаточно запустить приложение в режиме отладки:
call_vs_set.png


и это только основной вывод. Промежуточные операции внутри метода начинаются со знака >, но они конечно же не все отправляются в вывод.

WxMaper
Аватара пользователя
Администратор
 
Сообщения: 92
Благодарил (а): 8 раз
Поблагодарили: 4 раза
На самом деле вызов методов не так-то уж и просто реализовать с учетом того, что методы могут быть перегружены, а php имеет нестрогую типизацию =)

У меня есть идея как немного ускорить вызов методов: нужно всего-лишь отсортировать список доступных методов, так, чтобы на первом месте оказался наиболее подходящий по сигнатуре. Например, такой вызов
phpqt Код:
$object->someMethod(0, 0);

может подойти под такие сигнатуры:
phpqt Код:
someMethod(int, int);
someMethod(int, bool);
someMethod(int, string);
someMethod(bool, int);
someMethod(bool, bool);
someMethod(bool, string);
someMethod(string, int);
someMethod(string, bool);
someMethod(string, string);


но, вероятнее всего, для него подойдет только сигнатура someMethod(int, int) и её следует установить первой в списке вызовов, тогда можно попытаться вызвать метод с минимальными конверсиями.
Но такая ситуация усложняется, если метод будет вызван так:
phpqt Код:
$value = $numeric_only_lineEdit->text; // string "123"
$object->someMethod(0, $value);

в список попадёт строковый параметр, но очевидно, что он должен был быть числовым. В таком случае движок в первую очередь вызовет метод со строкой, который выполняет операцию some схоже, но совершенно по другому. И вот попробуй тут объясни новичку почему нужно писать не $value, а (int) $value :rolleyes2:

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

rinart73
Аватара пользователя
 
Сообщения: 36
Skype: art7emw
Поблагодарили: 2 раза
Может тогда переделать некоторые методы и конструкторы?
Т.е., вместо теоретического:
phpqt Код:
$variable = 5;
$instance->saveTo(0, $variable);

$variable = '5';
$instance->saveTo(0, $variable); //Упс, не туда...

Сделать что-то вроде этого?
phpqt Код:
$variable = 5;
$instance->saveToRegistry(0, $variable);

$variable = '5';
$instance->saveToRegistry(0, $variable); //Exception

$variable = '5.txt';
$instance->saveToFile(0, $variable);

Т.е. избавиться от части перегрузок вообще. Иначе действительно придется объяснять всем и тем самым делать php более строго типизированным.
Да, мы отойдем от ванильного Qt по документации, но и производительность вырастет и путаниц будет меньше.
Почетный страдалец фигней
Пилю load_ui_file :good2:


Вернуться в Вопрошайка

Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость
cron