Luca Ottaviano Ottimizzare applicazioni Qt Gui

Transcript

Luca Ottaviano Ottimizzare applicazioni Qt Gui
Luca Ottaviano
Ottimizzare applicazioni Qt Gui
Firenze, 8 luglio 2013
Chi sono
•
Luca Ottaviano
•
[email protected]
•
@lucaotta
•
Sviluppatore su sistemi embedded presso Develer
•
Qt certified developer
•
Sviluppatore Python
Luca Ottaviano – [email protected]
Prerequisiti
•
Conoscenza dei meccanismi di base di Qt
•
Signal/slots
•
Implicit sharing
•
Gestione della memoria tramite parent/child
•
Conoscenza di Qt GUI
•
Programma compilato su PC!
Luca Ottaviano – [email protected]
La vostra applicazione è compilabile su PC, vero?
•
Ciclo code – build – test molto più veloce
•
Strumenti di debugging più comodi
•
Possibilità di profilazione
•
Unit test
•
Doppia implementazione
Luca Ottaviano – [email protected]
Tips and tricks
•
Test dell'architettura nei file di progetto
•
Abilitare selettivamente il codice usando macro
•
Compilare sempre su PC e almeno una volta al giorno su board
Luca Ottaviano – [email protected]
Strumenti di profiling
•
Callgrind: tempo di esecuzione
•
Massif: occupazione di memoria
•
Qml profiler: tempo di esecuzione specifico per QML
Luca Ottaviano – [email protected]
Evitare i calcoli floating point
Luca Ottaviano – [email protected]
Floating point: tipologie
•
Soft: emulazione completa
•
Softfp: passare i parametri all'FPU nei registri interi
•
Hardfp: parametri di funzioni nei registri FPU
•
Disponibile da GCC 4.5
•
Cortex-A8
Riferimenti: http://wiki.debian.org/ArmHardFloatPort/VfpComparison
Luca Ottaviano – [email protected]
Floating point: performance
•
Emulazione molto lenta (50x – 100x) di hard float
•
Su processori piccoli (250 Mhz) si sente
•
Pochi calcoli sono ammessi
Luca Ottaviano – [email protected]
Esempio: widget di un grafico
Luca Ottaviano – [email protected]
Invocazione di funzioni tramite signal/slot
Luca Ottaviano – [email protected]
Signal/slots
•
Spezzano il flusso del codice
•
Difficile fare review
•
Sono sincroni (tranne un tipo)
•
Sono LENTI!
•
Circa 100x rispetto a chiamare lo slot direttamente
•
Evitarli nei loop stretti
Luca Ottaviano – [email protected]
Esempio: loop stretto con segnali
Widget::Widget(QObject *parent): QObject(parent){
connect(this, &Widget::sig1, this, &Widget::doSomething);
}
int Widget::entryPoint(int var) {
for (int i = 0; i < var; ++i) {
emit sig1(i);
// doSomething(i);
}
return var;
}
int Widget::doSomething(int i) {
return i + i;
}
Luca Ottaviano – [email protected]
Esempio: loop stretto con segnali (2)
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
QTime start;
start.start();
w.entryPoint(10000000);
qDebug() << "Time elapsed:" << start.elapsed();
return a.exec();
}
Luca Ottaviano – [email protected]
Esempio: risultati
•
•
Debug (= senza ottimizzazione)
•
Signal/slot = 853 ms
•
Function call = 35 ms
Release (= -02)
•
Signal/slot = 705 ms
•
Function call = 0 ms (!)
_ZN6Widget10entryPointEi():
401ac0: 89 f0 mov %esi,%eax
401ac2: c3 retq Luca Ottaviano – [email protected]
Styling tramite CSS
Luca Ottaviano – [email protected]
QWidget e i CSS
•
Non abusare dei CSS
•
•
Preferire uno stylesheet a livello di applicazione
•
•
La valutazione di un CSS è lenta
Minimizza l'uso di memoria
Usare le property per cambiare CSS applicato
Luca Ottaviano – [email protected]
Esempio: property vs nuovo stylesheet
// MyWidget.cpp
...
Qstring s = "QWidget[SecondFgColor=\"true\"] {color:#6FB2FF;}"
this­>setStyleSheet(s);
...
// CSS
QWidget[SecondFgColor="true"] {color:#6FB2FF;}
// MyWidget.cpp
...
this­>setProperty("SecondFgColor", true);
this­>style()­>polish(this);
...
Luca Ottaviano – [email protected]
Gestione della memoria
Luca Ottaviano – [email protected]
Tempo di vita degli oggetti
•
In C++ allocare un oggetto con new è un leak...
•
...a meno che non si distrugga con delete
•
...oppure si assegni il parent del Qobject
ATTENZIONE!
•
Finchè il parent resta vivo, gli oggetti restano in vita
Esempio: QTcpServer::nextPendingConnection()
Luca Ottaviano – [email protected]
Gestione della memoria (1)
int main (int argc, char **argv)
{
// setup the GUI and Qapplication
// ...
QPixmap splashPixmap( ":/img/splash.png" );
QSplashScreen splash(splashPixmap);
splash.show();
splash.finish(&main_window);
return app.exec()
}
Luca Ottaviano – [email protected]
Gestione della memoria (2)
MySplashScreen::MySplashScreen(const QString &path) :
QSplashScreen(QPixmap(path))
{
}
int main(int argc, char **argv)
{
// setup the GUI and Qapplication
// ...
MySplashScreen *splash = new MySplashScreen(":/img/splash.png");
splash­>setAttribute(Qt::WA_DeleteOnClose);
splash­>show();
splash­>finish(&main_window);
return app.exec();
}
Luca Ottaviano – [email protected]
Le dimensioni contano
•
Usare immagini di dimensioni giuste
•
Si usa solo la memoria necessaria
•
Attenzione a QpushButton e Qicon
•
Attenzione al GUI Designer!
•
Non condivide le pixmap tra form diverse
Luca Ottaviano – [email protected]
Usare hardware adeguato
•
1 pixmap 1024 x 768 x 32 sono 2.3 Mb di RAM
•
•
~3.5% su un sistema con 64 Mb
10 icone 50 x 50 x 32 sono 100 kb di RAM
•
~ 1% su un sistema con 64 Mb
•
Di solito ci sono centinaia di icone!
Luca Ottaviano – [email protected]
Font prerenderizzati (QPF2)
•
Font non scalabili (bitmap)
•
Dimensione fissa
•
Poco costo di CPU per gestirli (rispetto ai TTF)
•
Possono gestire tutte le lingue
Luca Ottaviano – [email protected]
Scrivere widget custom
•
I widget standard sono generici
•
Non molto efficienti
•
Ottimizzare usando il QPainter
•
Non riscrivere prima di aver fatto profiling!
Luca Ottaviano – [email protected]
Let's Talk
office
+39 055 3984627 (218)
e-mail
[email protected]
web
www.develer.com
twitter
@lucaotta
Credits
Le immagini sono prese dal libro “Pro Git”
http://git-scm.com/book