Principales problemas para los títulos de Windows
El grupo Relaciones para desarrolladores de tecnologías de juegos y gráficos de Microsoft Windows realiza análisis de rendimiento para muchos juegos de Windows cada año. Durante estas sesiones, obtenemos experiencia práctica para vincular los comentarios y las consultas del desarrollador que recibimos diariamente. En ocasiones, ayudamos a rastrear un misterioso accidente u otro problema en un título, lo que nos proporciona más información sobre los problemas que los desarrolladores están experimentando.
En este artículo se resaltan muchos de los problemas comunes que hemos visto en los juegos de PC de generación actual.
- Rendimiento limitado de CPU
- Administración de lotes deficiente
- Copia excesiva de memoria
- Uso excesivo del envío dinámico de dibujo
- Alta sobrecarga en el procesamiento de archivos
- Instalación lenta y frustrante
- Falta de consideración de la memoria física
- Sobresuficiencia en la conversión de frecuencia de muestreo de audio de Real-Time
- Fragmentación de la memoria virtual
- Manipulación del Word control de Floating-Point
- Instalación opcional del entorno de ejecución de DirectX
- Uso excesivo de la sincronización de subprocesos
- Uso de RDTSC
rendimiento de CPU-Limited
La gran mayoría de los juegos están limitados por el rendimiento de cpu en sistemas con unidades de procesamiento gráfico de alto rendimiento (GPU). Esto a veces se debe a un uso deficiente del procesamiento por lotes para envíos de dibujo, pero más normalmente, esto se debe a que otros sistemas de juegos que consumen una gran parte de los ciclos de CPU disponibles. En los pocos casos en los que hemos visto la GPU como limitación, la causa es muy alta velocidad de relleno o demanda de sombreador de píxeles, en la configuración de alta resolución o bajo rendimiento del sombreador de vértices por una tarjeta de vídeo.
Dado que la mayoría de los títulos están limitados por la CPU, los mayores resultados de rendimiento proceden de la optimización de sistemas de juegos con uso intensivo de CPU. Normalmente, los sistemas de inteligencia artificial o física y la lógica de detección de colisiones asociada son los principales consumidores de ciclos de CPU en aplicaciones de Microsoft Direct3D. Cualquier trabajo para mejorar estos sistemas puede mejorar el rendimiento general del juego.
Administración de lotes deficiente
Lograr un buen paralelismo con la GPU requiere que los lotes de dibujo contengan suficiente geometría y los sombreadores tienen la complejidad adecuada para mantener ocupada la tarjeta de vídeo, mientras que no usan tantos lotes que el búfer de comandos está inundado. En el hardware de generación actual, se recomienda aproximadamente 300 o menos envíos por lotes de dibujo por fotograma (menos en CPU de menor rendimiento) para evitar que el procesamiento del controlador del búfer de comandos se convierta en un cuello de botella de rendimiento. Algunas otras combinaciones de llamadas de estado de API y controladores pueden dar lugar a un costoso procesamiento de CPU (compilación de controladores de sombreadores, por ejemplo), por lo que se recomienda encarecidamente el análisis de rendimiento rutinario.
Copia excesiva de memoria
Durante el desarrollo de la mayoría de los títulos de PC, los desarrolladores usan estructuras de datos y cadenas convenientes para la administración de contenido. El trabajo de CPU necesario para la comparación de cadenas, la copia y otras manipulaciones suele tener una sobrecarga medible, especialmente cuando se tienen en cuenta los aciertos de rendimiento asociados con la memoria caché y el subsistema de memoria. Se deben realizar planes al desarrollar estos sistemas para eliminar o minimizar la dependencia del procesamiento de cadenas una vez que el producto entra en las fases de prueba y lanzamiento principales.
Uso excesivo del envío dinámico de dibujo
El hardware de vídeo moderno funciona bien cuando se trabaja con datos estáticos. Los adaptadores de gama alta suelen tener una gran cantidad de memoria de vídeo, pero esta memoria no se puede utilizar eficazmente con datos dinámicos.
Aunque se pueden implementar patrones de uso razonablemente eficientes de búferes de vértices dinámicos o búferes de índice para el contenido dinámico, muchos títulos sobreutilizan este lenguaje para lo que de otro modo es contenido estático. A menudo se ve esto con árboles de creación de particiones de espacio binario (BSP) y sistemas basados en portal que almacenan geometría en una estructura de datos que no se asigna al hardware y se deben procesar en búferes para cada fotograma. Colocar tanto contenido en recursos estáticos como sea posible puede reducir considerablemente la sobrecarga de ancho de banda de la transferencia de datos a la tarjeta de vídeo, hacer un mejor uso de VRAM incorporado y reducir la sobrecarga de CPU/caché implicada en el procesamiento de este contenido.
Alta sobrecarga en el procesamiento de archivos
Los juegos de PC han obtenido una reputación para tiempos de carga largos, en particular en comparación con los títulos de consola con requisitos estrictos de tiempo de carga. Nuestro análisis de la forma en que muchos títulos usan el subsistema de archivos revela algunos problemas comunes.
La sobrecarga de abrir un archivo suele ser mucho mayor de lo que esperan los desarrolladores. Con los escáneres de virus a petición en uso generalizado y la funcionalidad adicional de NTFS, abrir un archivo es una operación bastante costosa. Abrir muchos archivos a la vez o abrir y cerrar el mismo archivo repetidamente es un método deficiente de tratar con la administración de archivos. Algunos juegos han intentado mitigar este costo de rendimiento probando la existencia de un archivo antes de abrirlo. La realidad es que las pruebas para la existencia de un archivo en NTFS requieren abrir el archivo, por lo que las pruebas antes de abrir da como resultado pagar el costo dos veces.
Los juegos que permiten modificaciones de complementos, o mods, o que todavía incluyen scaffolding de desarrollo para comprobar si hay archivos de datos de invalidación, pueden tener retrasos significativos en la carga del juego debido a la comprobación de estos archivos, incluso cuando esos archivos no están presentes. Se recomienda que los juegos solo comprueben estos archivos cuando se ejecuten con un conmutador de línea de comandos especial u otro indicador de modo, de modo que solo los usuarios que usen esta funcionalidad paguen realmente el costo de rendimiento de estas comprobaciones (a menudo extensas).
El rendimiento adicional se puede obtener del sistema de archivos mediante lo siguiente:
- Uso adecuado de las sugerencias del sistema de archivos FILE_FLAG_RANDOM_ACCESS y FILE_FLAG_SEQUENTIAL_SCAN
- Cambiar el tamaño de los búferes para evitar una gran cantidad de llamadas a las API de lectura y escritura del sistema operativo
- Acceso a archivos de forma asincrónica
- Carga de subprocesos en segundo plano
También recomendamos encarecidamente convertir datos sin conexión (en tiempo de compilación o instalación) en lugar de confiar en la conversión cuando el juego se ejecuta por primera vez, ya que esto impone un impuesto de rendimiento significativo para cada usuario.
Instalación lenta y frustrante
Otro problema común que hemos visto es muy largo tiempo de instalación necesario para muchos juegos de PC modernos. Los instaladores solicitan al usuario muchas veces, a veces simplemente indicar al usuario, por ejemplo, "No necesita DirectX instalado". Por lo general, estos instaladores infractores requieren que el usuario seleccione Siguiente o Aceptar muchas veces antes de que se inicie realmente la instalación del juego. Una vez que empiece, hemos visto que algunos títulos tardan una hora o más antes de que el usuario obtenga la oportunidad de jugar al juego. Nos sentimos firmemente que la primera hora de la experiencia de juego no debe ser la instalación.
Se recomienda una serie de enfoques para tratar la instalación. En primer lugar, mantenga las indicaciones sencillas y a un mínimo. En segundo lugar, diseñe los datos del juego para que algunos o todos los archivos de datos se puedan usar directamente desde el disco de distribución siempre que sea posible, las unidades de DVD modernas tienen un ancho de banda muy alto. En tercer lugar, considere la posibilidad de implementar la instalación a petición en los títulos para reducir o eliminar el proceso de instalación y permitir que los usuarios entren en el juego lo antes posible. (Para obtener más información sobre la instalación a petición, consulta Install-on-Demand for Games).
Para obtener más recomendaciones sobre la instalación de juegos, consulta Simplificación de la instalación de juegos.
Falta de consideración de la memoria física
Debido a la amplia variabilidad del hardware de PC en el mercado, los títulos suelen usar pruebas de configuración ad hoc para seleccionar las opciones predeterminadas para el nivel de detalle gráfico. Algunos de los títulos que hemos visto usan el tamaño de memoria de vídeo en estas pruebas, pero no se puede correlacionar con el tamaño de memoria física. Para controlar situaciones de dispositivo perdido, la mayoría de la memoria de vídeo (VRAM local en la tarjeta y la apertura de memoria AGP no local) deben estar respaldadas por memoria física, ya sea mediante el uso de recursos administrados o estructuras de datos personalizadas. Algunas tarjetas de vídeo de gama alta tienen tamaños de VRAM que rivalizan con el tamaño de memorias de CPU de bajo nivel. En situaciones en las que el sistema tiene memoria física limitada en comparación con la tarjeta de vídeo, la mayoría de esa VRAM no se puede utilizar de forma eficaz y se deben configurar las opciones de detalles inferiores.
Over-Reliance en la conversión de frecuencia de muestreo de audio de Real-Time
Otro origen común de la grabación del ciclo de CPU que hemos visto se produce cuando se requiere el sistema de audio para convertir la velocidad de reproducción durante la mezcla en el búfer de hardware. Con los controladores del modelo de controlador de Windows (WDM), el formato del búfer de hardware no está bajo control directo de la aplicación, ya que es un recurso de nivel de kernel; en su lugar, el formato se selecciona en función del formato de mayor calidad de todos los orígenes y las funcionalidades del hardware. De forma predeterminada, Windows XP usa una conversión de frecuencia de muestreo de alta calidad para este proceso y, si la mayoría de las muestras de audio requieren una conversión de velocidad, se consumirá una parte significativa de los ciclos de CPU.
Se recomienda crear todos los búferes de DirectSound con la misma frecuencia de muestreo. Si usa las funciones waveOut de Microsoft Win32, también debe usar una frecuencia de muestreo coherente con estas. Con los controladores WDM, el kernel mezclará todos los búferes y, si usa una frecuencia de muestreo más alta en algunos de ellos, las tasas de muestreo de todo el resto se convertirán para que coincidan. Tenga en cuenta que esto implica el uso de la misma velocidad de reproducción para todas las muestras de audio, incluidos los búferes de descompresión de audio de streaming. Establecer la velocidad de búfer principal no tiene ningún efecto a menos que tenga como destino Windows 98 o Windows Millennium Edition.
Nota
En Windows Vista y versiones posteriores del sistema operativo, DirectSound y waveOut usan la API de sesión de audio de Windows (WASAPI) para toda la salida de audio.
Fragmentación de la memoria virtual
Hemos visto una serie de problemas recientes relacionados con el límite de 32 bits en el espacio de memoria del proceso. Aunque 2 GB de espacio de direcciones virtuales para los procesos en modo de usuario ha sido más de lo adecuado históricamente, el aumento del uso de archivos asignados a memoria grandes, asignadores de memoria personalizados y el aumento del tamaño de VRAM (que debe asignarse al espacio de proceso) ha comenzado a provocar situaciones en las que se producen errores en las asignaciones de espacio de memoria virtual. Algunos archivos DLL que no son de Microsoft usan ubicaciones de inicio fijo en medio del espacio de direcciones virtuales, lo que provoca fragmentación que da lugar a asignaciones erróneas.
Estos problemas a menudo aparecen cuando el juego usa un esquema de asignación de memoria personalizado que intenta asignar un gran fragmento continuo de espacio de memoria virtual. Nuestra recomendación es escribir asignadores de modo que soliciten partes de tamaño más razonable del espacio de direcciones virtuales según sea necesario. Por ejemplo, solicitando 64 o 256 MB a la vez, pero no 1 GB. Sin embargo, se debe tener cuidado para no provocar una fragmentación adicional. La llegada de sistemas operativos y hardware de 64 bits ayudará en gran medida a estos problemas en el futuro, pero se debe tener cuidado en los sistemas de 32 bits de generación actual.
Manipulación del Word control de Floating-Point
Como ayuda para la depuración, algunos desarrolladores han estado habilitando excepciones en la unidad de punto flotante (FPU) a través de manipulaciones de la palabra de control de punto flotante. Esto es muy problemático y probablemente hará que el proceso se bloquee. Al igual que la convención de llamada requiere que se conserve el registro ebx, la mayoría del sistema supone que la FPU está en un estado predeterminado, proporcionará resultados razonables y no generará excepciones. Los controladores y otros componentes del sistema suelen calcular los resultados en función de la suposición de que los valores de error estándar aparecerán en los registros de condiciones incorrectas, pero si las excepciones están habilitadas, estas se descontrolarán y darán lugar a bloqueos.
Direct3D establecerá la unidad de punto flotante en una sola precisión, redondeada a más cercana como parte de la inicialización para el subproceso que realiza la llamada, a menos que se use la marca de D3DCREATE_FPU_PRESERVE, en cuyo caso, la palabra de control de punto flotante no se modifica. Dado que la palabra de control es una configuración por subproceso, asegurarse de que todos los subprocesos de la aplicación están establecidos en modo de precisión única pueden optimizar el rendimiento. Recuerde que llamar a _control87 no es válido para la codificación nativa x64, que usa SSE exclusivamente en su lugar, y es extremadamente caro en la arquitectura basada en PowerPC de la CPU de Xbox 360.
Nota
Si modifica la palabra de control, use _controlfp_s y tenga en cuenta que para las plataformas x64 no puede cambiar la precisión de punto flotante a través de la palabra de control.
En las bibliotecas en las que es necesario tener reglas de redondeo diferentes u otro comportamiento , como trabajar con sombreadores de vértices de software o compilación, guardamos y restauramos la palabra de control. Si un juego necesita hacer uso de excepciones de redondeo o FPU no estándar, debe guardar y restaurar la palabra de control de punto flotante, y debes asegurarte de que no llama a ningún código externo que no se haya demostrado que sea seguro de estos problemas, incluidas las API del sistema.
Instalación opcional del entorno de ejecución de DirectX
Varios juegos preguntan al usuario si instalar DirectX. Esto puede causar problemas si el usuario asume que el sistema tiene instalado el redistribuible DirectX más reciente y omite la instalación y, posteriormente, la instalación continúa correctamente. Si el juego requiere una versión específica de D3DX u otra funcionalidad actualizada que no se instaló, el juego no funcionará y el usuario se frustrará mucho.
Se recomienda encarecidamente que el instalador del juego instale silenciosamente el redistribuible DirectX en el que se creó el juego. El proceso de instalación de DirectX está diseñado para que compruebe si es necesario actualizar algo y devuelve rápidamente si no lo hace. Por lo tanto, no es necesario preguntar al usuario sobre la instalación de DirectX.
Para realizar una instalación silenciosa de DirectX, ejecute este comando desde el paquete de instalación: dxsetup.exe /silent
Además, el tamaño real de la carpeta redistribuible se puede configurar para incluir solo los archivos de gabinete (.cab) que realmente son necesarios para las plataformas de destino y el uso del juego.
Nota
Antes de usar dxsetup, lea Not So Direct Setup.
Uso excesivo de la sincronización de subprocesos
Al generar perfiles de juegos, a menudo se encuentran los puntos de acceso principales relacionados con la entrada y salida de secciones críticas. Con la prevalencia de las CPU de varios núcleos, el uso de multithreading en juegos ha aumentado drásticamente y muchas implementaciones dependen del uso intensivo de la sincronización de subprocesos. El tiempo de CPU para tomar una sección crítica incluso sin ninguna contención es bastante significativo, y todas las demás formas de sincronización de subprocesos son aún más costosas. Por lo tanto, se debe tener cuidado para minimizar el uso de estos primitivos.
Una fuente común de sincronización excesiva en los juegos es el uso de D3DCREATE_MULTITHREADED. Esta marca, al tiempo que hace que los subprocesos de Direct3D sean seguros para la representación desde varios subprocesos, adopta un enfoque muy conservador, lo que da lugar a una sobrecarga de sincronización elevada. Los juegos deben evitar esta bandera. En su lugar, diseñe el motor para que toda la comunicación con Direct3D sea de un único subproceso y cualquier comunicación entre subprocesos se controle directamente. Para obtener más información sobre el diseño de juegos multiproceso, consulta el artículo Codificación para varios núcleos en Xbox 360 y Microsoft Windows.
Uso de RDTSC
No se recomienda el uso de la instrucción RDTSC x86. RDTSC no puede calcular correctamente el tiempo en algunos esquemas de administración de energía que cambian la frecuencia de CPU dinámicamente y en muchas CPU de varios núcleos para las que el contador de ciclo no está sincronizado entre núcleos. En su lugar, los juegos deben usar la API QueryPerformanceCounter . Para obtener más información sobre los problemas con RDTSC e implementar el control de tiempo de alta resolución con QueryPerformanceCounter, consulta el artículo Control de tiempo de juego y procesadores multicore.