2009-02-02 8 views
13

Tutti voi Stackoverflowers,Perché il codice della GUI è così costoso dal punto di vista computazionale?

Mi chiedevo perché il codice GUI è responsabile per succhiare via molti cicli di CPU. In linea di principio, il rendering grafico è molto meno complesso di Doom (sebbene la maggior parte delle GUI aziendali introdurrà molte finestre). Il livello di gestione degli eventi è anche apparentemente un costo pesante, tuttavia, sembra che un'implementazione ben scritta dovrebbe passare in modo efficiente da un contesto all'altro sui processori moderni con un sacco di memoria/cache.

Se qualcuno ha eseguito un profiler sulla loro grande applicazione GUI o su una API comune, sono interessato a dove si trovano i colli di bottiglia.

possibili spiegazioni (che immagino) possono essere:

  1. Alti livelli di astrazione tra l'hardware e interfaccia dell'applicazione
  2. Un sacco di livelli di riferimento indiretto al codice corretto per eseguire
  3. bassa priorità (rispetto ad altri processi)
  4. Applicazioni anomale flooding API con chiamate
  5. Eccessivo orientamento dell'oggetto?
  6. completi povere scelte progettuali in API (non solo i problemi, ma la filosofia di design)

Alcuni framework GUI sono molto meglio di altri, quindi mi piacerebbe sentire prospettive diverse. Ad esempio, il sistema Unix/X11 è molto diverso da Windows e persino da WinForms.

Modifica: Ora un wiki della comunità: prendilo. Ho ancora una cosa da aggiungere - Sono un ragazzo degli algoritmi a scuola e sarei interessato se ci sono algoritmi inefficienti nel codice della GUI e quali sono. Quindi, di nuovo, è probabilmente solo l'overhead di implementazione.

+0

Sono anche molto interessato a questo. Non può essere che il gui sia renderizzato usando solo la CPU perché se non hai i driver corretti per la tua gfx-card, la grafica del desktop render _incredibly_ slow. Se hai i driver gfx, tuttavia, desktop-gfx è veloce ma mai veloce come un'applicazione directx/opengl. –

+0

Gli unici algoritmi che sono probabilmente lenti sono gli algoritmi di rendering del software, ma le GUI si stanno allontanando da quello –

risposta

9

Non ho idea in generale, ma mi piacerebbe aggiungere un altro elemento alla vostra lista - rendering dei font e calcoli. Trovare i glifi vettoriali in un font e convertirli in rappresentazioni bitmap con anti-aliasing non è un compito da poco. E spesso deve essere fatto due volte: prima per calcolare la larghezza/altezza del testo per il posizionamento, e quindi effettivamente disegnare il testo alle coordinate corrette.

Inoltre, la maggior parte del codice di disegno oggi si basa sui meccanismi di ritaglio per aggiornare solo una parte della GUI. Quindi, se è necessario ridisporre solo una parte, il codice ridisegna effettivamente l'intera finestra dietro le quinte, quindi prende solo la parte necessaria per l'aggiornamento effettivo.

Aggiunto:

Nei commenti ho trovato questo:

Sono molto interessato a questo anche. Non può essere che il gui sia renderizzato usando solo la CPU perché se non hai i driver corretti per la tua gfx-card, la grafica del desktop rende incredibilmente lento. Se hai i driver gfx, tuttavia, desktop-gfx è veloce ma mai veloce come un'applicazione directx/opengl.

Ecco l'accordo come ho capito: ogni scheda grafica là fuori oggi supporta un'interfaccia generica per il disegno. Non sono sicuro che si chiami "VESA", "SVGA" o se sono solo vecchi nomi del passato.Ad ogni modo, questa interfaccia implica di fare tutto attraverso gli interrupt. Per ogni pixel c'è una chiamata di interrupt. O qualcosa di simile. Tuttavia, il driver VGA appropriato è in grado di trarre vantaggio dal DMA e da altri miglioramenti che rendono l'intero processo WAY meno impegnativo per la CPU.

Aggiunto 2: Ah, e per OpenGL/DirectX - questa è un'altra caratteristica delle schede grafiche di oggi. Sono ottimizzati per le operazioni 3D in modalità esclusiva. Ecco perché la velocità. La normale interfaccia grafica utilizza solo le procedure di disegno 2D di base. Quindi arriva a inviare il contenuto di tutto lo schermo ogni volta che vuole un aggiornamento. Le applicazioni 3D tuttavia inviano una serie di trame e definizioni triangolari alla VRAM (video-RAM) e quindi le riutilizzano solo per il disegno. Dicono solo qualcosa come "prendi il triangolo # 38 con il set di texture # 25 e disegnali". Tutte queste cose sono memorizzate nella cache della VRAM, quindi questo è di nuovo molto più veloce.

Non ne sono sicuro, ma sospetto che le moderne GUI con accelerazione 3D (Vista Aero, compiz su Linux, ecc.) Possano trarne vantaggio. Potrebbero inviare comuni bitmap al VGA in primo piano e quindi riutilizzarli direttamente dalla VRAM. Qualsiasi superficie disegnata da un'applicazione, tuttavia, dovrebbe comunque essere inviata direttamente ogni volta per gli aggiornamenti.

Aggiunto 3: Altre idee. :) Le moderne GUI per Windows, Linux, ecc. Sono orientate ai widget (che è orientato al controllo per gli altoparlanti Windows). Il problema con questo è che ogni widget ha il proprio codice di disegno e superficie di disegno associata (più o meno). Quando la finestra deve essere ridisegnata, chiama il codice di disegno per tutti i suoi widget figlio, che a loro volta chiamano il codice di disegno per i loro widget figlio, ecc. Ogni widget ridisegna l'intera superficie, anche se alcuni di essi sono oscurati da altri widget. Con le tecniche di ritaglio sopra menzionate, alcune di queste informazioni disegnate vengono immediatamente scartate per ridurre lo sfarfallio e altri artefatti. Ma è ancora un sacco di codice di disegno manuale che include il bitmap, lo stretching, l'inclinazione, il disegno di linee, il testo, il riempimento, ecc. E tutto questo viene tradotto in una serie di chiamate putpixel filtrate attraverso filtri/maschere di ritaglio e altro cose. Ah, sì, e l'alpha blending è diventato popolare anche oggi per effetti piacevoli che significano ancora più lavoro. Quindi ... si, si potrebbe dire che questo è dovuto a molta astrazione e indiretta. Ma ... potresti davvero farlo meglio? Io non la penso così Solo le tecniche 3D possono essere d'aiuto, perché sfruttano la GPU per il calcolo e il ritaglio alfa.

+0

Come si menziona il suo 80% sul rendering. La maggior parte dei giochi utilizza GUI basata su poligoni, quindi il rendering è basato su scheda video al 100% ed è molto più veloce della media GUI del PC, ma le nuove GUI come menzionate stanno diventando più intelligenti con il loro rendering, quindi la perfromance GUI dovrebbe diventare banale in un pochi anni –

+0

Sai, il parallelismo dei dati non è limitato all'applicazione 3D ... Puoi fare altrettanto bene con 2D, l'accelerazione con scheda video NON è una soluzione, è in un guscio di noce la stessa logica che dice che il mio programma funziona lentamente, compra un computer più veloce. I titoli di gioco AAA richiedono uno sforzo ridicolo per correre velocemente. –

+0

Sono d'accordo. Ma a meno di ricorrere al tipo di trucchi di programmazione che tutti i libri di buona pratica ci mettono in guardia, non vedo nessun altro modo di migliorare le cose. Hai un'idea migliore su come organizzare un rendering dell'interfaccia utente basato su widget? –

2

Uhm, questo è un bel po '.

La risposta più semplice, ma probabilmente ovvia, è che i programmatori dietro queste app GUI sono davvero dei pessimi programmatori. Puoi andare avanti scrivendo il codice che fa le cose più bizzarre e sarà più veloce ma a poche persone sembra importare come fare questo o lo ritengono un costoso spreco di tempo non redditizio.

Per impostare le cose in modo corretto, i calcoli del carico sulla GPU non risolveranno necessariamente alcun problema. La GPU è esattamente come la CPU, tranne che per uno scopo meno generale e per un processore parallelo di dati. Può fare calcoli grafici eccezionalmente bene. Qualunque sia la grafica API/OS e la combinazione di driver che hai non importa molto ... beh OK, con Vista come esempio, hanno cambiato il motore di composizione del desktop. Questo motore è di gran lunga migliore rispetto a quello che è cambiato, e dal momento che il numero uno per le applicazioni della GUI è il ridisegno è una strategia di ottimizzazione ordinata. Questa idea di virtualizzazione dei tuoi bisogni computazionali e aggiorna solo il più piccolo cambiamento ogni volta.

Win32 invia i messaggi WM_PAINT a Windows quando devono essere ridisegnati, questo può essere il risultato di finestre che si occludono a vicenda. Tuttavia tocca alla finestra stessa capire che cosa è effettivamente cambiato. Più di così non è cambiato nulla o il cambiamento che è stato fatto è stato abbastanza banale in modo che avrebbe potuto essere solo preformato in cima a quello che mai più in alto superficie hai avuto.

Questo tipo di gestione della grafica non esiste necessariamente oggi. Direi che le persone si sono astenute dallo scrivere soluzioni di rendering veramente efficienti e virtualizzate perché il rapporto costi/benefici è piuttosto basso/alto (cattivo).

Ciò che fa Windows Presentation Foundation (WPF), che ritengo sia di gran lunga superiore alla maggior parte delle altre API della GUI, è che divide gli aggiornamenti del layout e il rendering degli aggiornamenti in due passaggi separati. E mentre il codice di gestione WPF è gestito, il motore di rendering non lo è. Ciò che accade con il rendering è che il motore di rendering WPF gestito crea una coda di comando (questo è ciò che fa DirectX e OpenGL), che viene poi trasmessa al motore di rendering nativo. Ciò che è un po 'più elegante qui è che WPF tenterà quindi di conservare qualsiasi computazione che non abbia modificato lo stato visivo. Un trucco, se possibile, in cui si evitano costose chiamate di rendering per cose che non devono essere renderizzate (virtualizzazione).

Al contrario di WM_PAINT che indica a una finestra Win32 di ridisegnarsi da sé, un'app WPF controlla quali parti di tale finestra richiedono la ridipinture e si limitano a ridipingere la modifica più piccola.

Ora WPF non è il massimo, è un grosso sforzo di Microsoft ma non è ancora il Santo Graal ... il codice che esegue la pipeline potrebbe ancora essere migliorato e l'impronta di memoria di qualsiasi app gestita è ancora più di quanto vorrei volere. Ma spero che questo sia il tipo di risposta che stai cercando.

WPF è in grado di fare alcune cose in modo asincrono piuttosto decente, il che è un grosso problema se si vuole realizzare un'interfaccia utente a bassa latenza/bassa cpu veramente reattiva. Le operazioni asincrone sono più che il lavoro di scarico su un thread diverso.

Per riassumere le cose lente e costose GUI significa troppo ridipingere e il tipo di riverniciatura che è molto costoso, cioè l'intera superficie.

+0

WM_PAINT dice solo che la pittura potrebbe dover essere eseguita in alcune parti di una finestra. GetUpdateRgn ti consente di capire quali parti devono essere ridisegnate. La maggior parte dei controlli complessi esegue il rendering su una bitmap e blit sull'occlusione, quindi non vedo WPF che aiuta molto, eseguito per codice di rendering scritto in modo scadente. –

0

In qualche misura dipende dalla lingua. Avrai notato che le applicazioni Java e RealBasic sono un po 'più lente delle loro controparti basate su C (C++, C#, Objective-C).

Tuttavia, le applicazioni GUI sono molto più complesse delle applicazioni a riga di comando. La finestra Terminale deve solo disegnare una semplice finestra che non supporta i pulsanti.

Ci sono anche loop multipli per ingressi e funzionalità extra.

5

Iniziamo col dire che scrivere librerie è molto più difficile che scrivere un codice autonomo. Il requisito che la tua astrazione sia riusabile in quanti più contesti possibili, compresi i contesti che non hai ancora, rende il compito impegnativo anche per i programmatori esperti.

Tra le librerie, scrivere una libreria di toolkit GUI è un problema notoriamente difficile. Questo perché i programmi che utilizzano le librerie GUI spaziano su una vasta gamma di domini con esigenze molto diverse. Mr Why e Martin DeMollo discussed the requirements placed of GUI libraries poco fa.

Scrivere gli stessi GUI è difficile perché gli utenti di computer sono dettagli molto delicati del comportamento dell'interfaccia. Il widget non nativo non si sente mai giusto, vero? Per ottenere correttamente il widget non nativo, al fine di ottenere correttamente qualsiasi widget, è necessario passare una quantità eccessiva di tempo modificando i dettagli del comportamento.

Quindi, le GUI sono lente a causa delle inefficienze introdotte dai meccanismi di astrazione utilizzati per creare componenti altamente riutilizzabili, che hanno aggiunto alla mancanza di tempo a disposizione per ottimizzare il codice una volta trascorso così tanto tempo a ottenere il giusto comportamento.

+0

+1. Sono d'accordo con i tuoi punti; ma ci sono due influenze molto distinte al lavoro qui. Quello che dichiari porta a librerie GUI che utilizzano più cicli di quanto sarebbe strettamente necessario. Tuttavia, ho trovato che l'uso sconsiderato/inesperto di toolkit GUI può costare ancora più prestazioni. – mghie

0

Penso che si possano trovare alcune riflessioni interessanti su questo argomento in "Window System Design: Se dovessi farlo di nuovo nel 2002" di James Gosling (il ragazzo di Java, noto anche per il suo lavoro su pre-X11 sistemi di finestre). Disponibile online here[pdf].

L'articolo si concentra sul lato positivo (come renderlo veloce), non sul lato negativo (cosa lo rende lento), ma è comunque una buona lettura sull'argomento.

Problemi correlati