2009-02-02 12 views
13

Todo lo que Stackoverflowers,¿Por qué el código GUI es tan costoso desde el punto de vista computacional?

Me preguntaba por qué el código GUI es responsable de la succión de muchos, muchos ciclos de CPU. En principio, la representación gráfica es mucho menos compleja que Doom (aunque la mayoría de las GUI corporativas introducirán gran cantidad de escaparates). La capa de manejo de eventos también es aparentemente un gran costo, sin embargo, parece que una implementación bien escrita debe cambiar entre contextos de manera eficiente en procesadores modernos con mucha memoria/caché.

Si alguien se ha quedado un generador de perfiles en su gran aplicación GUI, o el propio API común, estoy interesado en donde se encuentran los cuellos de botella.

explicaciones

posibles (que imagino) pueden ser:

  1. altos niveles de abstracción entre el hardware y la interfaz de la aplicación
  2. Muchos de los niveles de indirección al código correcto para ejecutar
  3. Prioridad baja (comparada a otros procesos)
  4. Aplicaciones incorrectas inundaciones API con llamadas
  5. ¿Orientación excesiva del objeto?
  6. opciones de diseño pobre completas en API (no sólo los problemas, pero la filosofía de diseño)

Algunos marcos GUI son mucho mejores que otros, así que me gustaría escuchar diversas perspectivas. Por ejemplo, el sistema Unix/X11 es muy diferente de Windows e incluso de WinForms.

Editar: Ahora una wiki de la comunidad - hazlo. Tengo algo más que añadir: soy un tipo de algoritmo en la escuela y me interesaría si hay algoritmos ineficientes en el código GUI y cuáles son. Por otra parte, es probable que solo sea la sobrecarga de implementación.

+0

También estoy muy interesado en esto. No puede ser que la interfaz gráfica de usuario se represente solo con la CPU porque si no tiene los controladores adecuados para su tarjeta gfx, los gráficos de escritorio se vuelven _incredibly_ lentos. Si tienes gfx-drivers, sin embargo, desktop-gfx funciona un poco rápido, pero nunca tan rápido como una aplicación de Directx/OpenGL. –

+0

Los únicos algoritmos que probablemente sean lentos son los algoritmos de representación de software, pero las GUI se están alejando de ese –

Respuesta

9

no tengo idea general, pero me gustaría añadir otro elemento a la lista - Representación de fuentes y cálculos. Encontrar glifos vectoriales en una fuente y convertirlos en representaciones de mapa de bits con anti-aliasing no es tarea fácil. Y a menudo tiene que hacerse dos veces: primero para calcular el ancho/alto del texto para el posicionamiento, y luego dibujar el texto en las coordenadas correctas.

Además, la mayoría código de dibujo actual se basa en mecanismos de recorte para actualizar sólo una parte de la interfaz gráfica de usuario. Por lo tanto, si solo se necesita volver a dibujar una parte, el código en realidad vuelve a dibujar toda la ventana detrás de las escenas, y luego solo toma la parte necesaria para actualizarse realmente.

Agregado:

En los comentarios que encontré esto:

también estoy muy interesado en esto. No puede ser que la GUI se represente usando solo la CPU porque si no tiene los controladores adecuados para su tarjeta gfx, los gráficos de escritorio rinden increíblemente lento. Si tienes gfx-drivers, sin embargo, desktop-gfx funciona un poco rápido, pero nunca tan rápido como una aplicación de Directx/OpenGL.

Aquí está el acuerdo tal como lo entiendo: todas las tarjetas gráficas que hay hoy en día admiten una interfaz genérica para dibujar. No estoy seguro si se llama "VESA", "SVGA", o si solo se trata de nombres antiguos del pasado.De todos modos, esta interfaz implica hacer todo a través de interrupciones. Por cada píxel hay una llamada de interrupción. O algo así. Sin embargo, el controlador VGA adecuado es capaz de aprovechar DMA y otras mejoras que hacen que todo el proceso sea mucho menos intenso.

Agregado 2: Ah, y para OpenGL/DirectX: esa es otra característica de las tarjetas gráficas de hoy en día. Están optimizados para operaciones 3D en modo exclusivo. Es por eso que la velocidad. La GUI normal solo utiliza procedimientos básicos de dibujo en 2D. Por lo tanto, envía los contenidos de la pantalla completa cada vez que quiere una actualización. Sin embargo, las aplicaciones 3D envían un montón de texturas y definiciones de triángulos a la VRAM (video-RAM) y luego solo las reutilizan para dibujar. Simplemente dicen algo como "toma el triángulo establecido # 38 con el conjunto de textura # 25 y dibuja". Todas estas cosas están almacenadas en caché en la VRAM, así que esto es mucho más rápido.

No estoy seguro, pero sospecho que las modernas GUI aceleradas en 3D (Vista Aero, compiz en Linux, etc.) también podrían aprovechar esto. Podrían enviar mapas de bits comunes al VGA por adelantado y luego simplemente reutilizarlos directamente desde la VRAM. Sin embargo, cualquier superficie dibujada por la aplicación debería enviarse directamente cada vez para recibir actualizaciones.

Agregado 3: Más ideas. :) Las GUI modernas para Windows, Linux, etc. están orientadas a widgets (orientadas al control para altavoces de Windows). El problema con esto es que cada widget tiene su propio código de dibujo y superficie de dibujo asociada (más o menos). Cuando la ventana necesita volverse a dibujar, llama al código de dibujo para todos sus widgets secundarios, que a su vez llaman al código de dibujo para sus widgets hijos, etc. Cada widget vuelve a dibujar toda su superficie, aunque parte de ella está oscurecida. por otros widgets. Con las técnicas de recorte mencionadas anteriormente, parte de esta información extraída se descarta inmediatamente para reducir el parpadeo y otros artefactos. Pero aún así hay un montón de código de dibujo manual que incluye blitting de mapas de bits, estiramientos, sesgos, líneas de dibujo, texto, llenado de inundaciones, etc. Y todo esto se traduce en una serie de llamadas de putpixel que se filtran a través de filtros de recorte/máscaras y otras cosas. Ah, sí, y la mezcla alfa también se ha hecho popular hoy en día para efectos agradables, lo que significa aún más trabajo. Entonces ... sí, se podría decir que esto se debe a mucha abstracción e indirección. Pero ... ¿podrías hacerlo mejor? No lo creo. Solo las técnicas 3D pueden ser útiles, ya que aprovechan la GPU para realizar cálculos alfa y clipping.

+0

Como mencionas, es 80% sobre la representación. La mayoría de los juegos usan GUIs basadas en polígonos, por lo que el renderizado está 100% basado en tarjetas de video, y es mucho más rápido que la GUI de PC promedio, pero las GUI más nuevas como mencionas se vuelven más inteligentes con su renderizado, por lo que el rendimiento de la GUI debería ser trivial. algunos años –

+0

Ya sabes, el paralelismo de datos no se limita a la aplicación 3D ... Puedes hacerlo igual de bien con 2D, la aceleración de la tarjeta de video NO es una solución, es una cáscara de nuez la misma lógica que decir que mi programa funciona lento, compre una computadora más rápida. Los títulos de juegos de AAA requieren una cantidad ridícula de esfuerzo para correr rápido. –

+0

Estoy de acuerdo. Pero, sin recurrir a los trucos de programación que todos los libros de buenas prácticas nos advierten, no veo otra forma de mejorar las cosas. ¿Tiene una mejor idea sobre cómo organizar una representación de UI basada en widgets? –

2

Uhm, eso es mucho.

La respuesta más simple pero probablemente obvia es que los programadores detrás de estas aplicaciones GUI, son realmente malos programadores. Puedes avanzar en la escritura de código que hace las cosas más extrañas y será más rápido, pero a pocas personas parece importarles cómo hacerlo o lo consideran un esfuerzo costoso, no rentable, que se desperdicia en el tiempo.

Para configurar las cosas directamente, los cálculos de carga en la GPU no necesariamente arreglarán ningún problema. La GPU es como la CPU, excepto que es un propósito menos general y más un procesador paralelo de datos. Puede hacer cómputos gráficos excepcionalmente bien. Cualquier combinación gráfica de API/OS y controlador que tengas realmente no importa tanto ... bueno, con Vista como ejemplo, cambiaron el motor de composición de escritorio. Este motor es mucho mejor para compostar solo lo que ha cambiado, y dado que el cuello de botella número uno para aplicaciones de GUI está redibujando es una estrategia de optimización ordenada. Esta idea de virtualizar sus necesidades computacionales y solo actualiza el cambio más pequeño cada vez.

Win32 envía mensajes WM_PAINT a Windows cuando necesitan volver a dibujarse, esto puede deberse a que Windows se ocluye entre sí. Sin embargo, depende de la ventana descubrir cuál ha cambiado realmente. Más que nada, nada cambió o el cambio que se hizo fue lo suficientemente trivial para que pudiera haberse realizado sobre la superficie más alta que tenías.

Este tipo de manejo de gráficos no existe hoy en día. Diría que las personas se han abstenido de escribir soluciones de renderizado realmente eficientes y virtuales porque la relación beneficio/costo es bastante baja/alta (mala).

Algo que Windows Presentation Foundation (WPF) hace, que creo que es muy superior a la mayoría de otras API de GUI es que divide las actualizaciones de diseño y las actualizaciones de representación en dos pasadas separadas. Y mientras que WPF es código administrado, el motor de representación no lo es. Lo que sucede con la representación es que el motor de representación gestionado de WPF crea una cola de comandos (esto es lo que hace DirectX y OpenGL) que luego pasa al motor de representación nativo. Lo que es un poco más elegante aquí es que WPF intentará retener cualquier cálculo que no cambie el estado visual. Un truco, si es posible, donde se evitan las llamadas costosas de representación de cosas que no tienen que ser renderizadas (virtualización).

En contraste con WM_PAINT que le dice a una ventana de Win32 que vuelva a pintar, una aplicación de WPF verificará qué partes de esa ventana requieren repintar y solo volver a pintar el cambio más pequeño.

Ahora WPF no es supremo, es un esfuerzo sólido de Microsoft, pero aún no es el santo grial ... el código que ejecuta la tubería aún podría mejorarse y la memoria de cualquier aplicación administrada es aún más de lo que yo querer. Pero espero que este sea el tipo de respuesta que estás buscando.

WPF puede hacer algunas cosas asincrónicamente bastante decente, que es una gran cosa si quieres hacer una interfaz de usuario de baja latencia/baja CPU realmente sensible. Las operaciones asincrónicas son más que trabajos de descarga en un hilo diferente.

Para resumir las cosas, la GUI lenta y costosa significa demasiado repintar y el tipo de repintado, que es muy caro, es decir, toda la superficie.

+0

WM_PAINT solo dice que es posible que haya que realizar la pintura en alguna parte de una ventana. GetUpdateRgn te permite descubrir qué partes necesitan volver a dibujar. La mayoría de los controles complejos se procesan en un mapa de bits y se recuperan de la oclusión, por lo que no veo que WPF ayude demasiado, excepto por el código de representación escrito. –

0

Hasta cierto punto, dependo del idioma. Habrá notado que las aplicaciones Java y RealBasic son bastante más lentas que sus contrapartes basadas en C (C++, C#, Objective-C).

Sin embargo, las aplicaciones GUI son mucho más complejas que las aplicaciones de línea de comandos. La ventana de Terminal solo necesita dibujar una ventana simple que no admita botones.

También hay múltiples bucles para entradas y funciones adicionales.

5

Comencemos diciendo que escribir bibliotecas es mucho más difícil que escribir un código independiente. El requisito de que su abstracción sea reutilizable en tantos contextos como sea posible, incluidos los contextos que aún no ha tenido, hace que la tarea sea desafiante incluso para programadores experimentados.

Entre las bibliotecas, escribir una biblioteca GUI toolkit es un problema muy difícil. Esto se debe a que los programas que usan bibliotecas GUI abarcan una amplia variedad de dominios con necesidades muy diferentes. Sr. Why y Martin DeMollo discussed the requirements placed of GUI libraries hace un momento.

Escribir los widgets de la GUI es difícil porque los usuarios de la computadora son detalles minuciosos muy sensibles del comportamiento de la interfaz. Widget no nativo nunca se siente bien, ¿no? Para poder obtener el widget no nativo correcto, para que cualquier widget sea correcto, de hecho, necesita pasar un tiempo desorbitado ajustando los detalles del comportamiento.

Por lo tanto, las GUI son lentas debido a las ineficiencias introducidas por los mecanismos de abstracción utilizados para crear componentes altamente reutilizables, que aumentan la falta de tiempo disponible para optimizar el código una vez que se ha gastado el comportamiento correcto.

+0

+1. Estoy de acuerdo con tus puntos; pero hay dos influencias muy distintas en juego aquí. Lo que usted declara lleva a que las bibliotecas de GUI consuman más ciclos de los estrictamente necesarios. Sin embargo, he encontrado que el uso irreflexivo e inexperto de los juegos de herramientas GUI puede costar mucho más rendimiento aún. – mghie

0

Creo que puede encontrar algunas ideas interesantes sobre este tema en "Diseño de sistema de ventanas: si lo tuviera que repetir en 2002" por James Gosling (el chico de Java, también conocido por su trabajo en pre-X11 sistemas de ventanas). Disponible en línea here[pdf].

El artículo se centra en el lado positivo (cómo hacerlo rápido), no en el lado negativo (lo que lo hace lento), pero sigue siendo una buena lectura sobre el tema.

Cuestiones relacionadas