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