Modelos comunes para aplicaciones multiproceso con comportamiento deficiente
El visualizador de simultaneidad ayuda a los desarrolladores a visualizar el comportamiento de una aplicación multiproceso.Esta herramienta contiene una galería de modelos comunes de aplicaciones multiproceso que no tienen un comportamiento correcto.La galería incluye modelos visuales típicos y reconocibles que se exponen a través de la herramienta junto con una explicación del comportamiento que cada modelo representa, el resultado probable de ese comportamiento y el enfoque más común para resolverlo.
Contención de bloqueo y ejecución serializada
A veces, una aplicación paralelizada sigue ejecutándose de forma serializada sin descanso a pesar de tener varios subprocesos y de que el equipo tiene un número suficiente de núcleos lógicos.El primer síntoma es un rendimiento pobre, quizás incluso un poco más lento que la implementación en serie.En la vista de subprocesos, no ve varios subprocesos que se ejecutan en paralelo, sino que solo ve que se está ejecutando un subproceso en cualquier hora.En este punto, si hace clic en un segmento de sincronización en un subproceso, puede ver una pila de llamadas para el subproceso bloqueado (pila de llamadas de bloqueo) y el subproceso que quitó la condición de bloqueo (pila de llamadas de desbloqueo).Además, si la pila de llamadas de desbloqueo se produce en el proceso que está analizando, se muestra un conector preparado para subprocesos.De aquí, se puede navegar hasta el código desde las pilas de llamadas de bloqueo y desbloqueo para investigar la causa de la serialización aún más.
Como se muestra en la siguiente ilustración, el visualizador de simultaneidad también puede mostrar este síntoma en la vista Utilización de CPU, donde, a pesar de la presencia de varios subprocesos, la aplicación solamente usa un núcleo lógico.
Para obtener más información, vea "Performance Pattern 1: Identifying Lock Contention" en el blog Parallel Performance Tools For Windows de Hazim Shafi, en el sitio web de blogs de MSDN.
Distribución desigual de la carga de trabajo
Cuando en una aplicación se produce una distribución irregular de trabajo por varios subprocesos paralelos, un paso modelo típico aparece cuando cada subproceso completa el trabajo, como se muestra en la ilustración anterior. El visualizador de simultaneidad muestra con mayor frecuencia horas de inicio muy próximas para cada subproceso simultáneo.Sin embargo, estos subprocesos normalmente finalizan de forma desigual y no terminan simultáneamente.Este modelo indica una distribución irregular del trabajo entre un grupo de subprocesos paralelos, lo cual puede reducir el rendimiento.El mejor enfoque para este tipo de problemas consiste en volver a evaluar el algoritmo por el que se ha dividido el trabajo entre los subprocesos paralelos.
Tal y como se muestra en la siguiente ilustración, el visualizador de simultaneidad también puede manifestar este síntoma en la vista Utilización de la CPU como un descenso gradual en el uso de la CPU.
Suscripción excesiva
En el caso de la suscripción excesiva, el número de subprocesos activos de un proceso es mayor que el número de núcleos lógicos disponibles en el sistema.En la ilustración anterior se muestran los resultados de la suscripción excesiva, con un adelantamiento (preemption) significativo en todos los subprocesos activos.Además, la leyenda indica que se invierte un porcentaje de tiempo importante en el adelantamiento (84 por ciento en este ejemplo).Esto puede indicar que el proceso está solicitando al sistema que ejecute un número mayor de subprocesos simultáneos que el número de núcleos lógicos.Sin embargo, también puede indicar que otros procesos del sistema están usando recursos que en teoría deberían estar disponibles para este proceso.
Debe tener en cuenta lo siguiente al evaluar este problema:
El sistema global puede presentar una suscripción excesiva.Tenga en cuenta que otros procesos del sistema pueden estar adelantándose a sus subprocesos.Si descansa el puntero del mouse sobre el segmento de adelantamiento en la vista de subprocesos, aparecerá una información sobre herramientas donde se identifican el subproceso y el proceso que se han adelantado al subproceso.Este proceso no tiene que ser necesariamente el único proceso que se ha ejecutado durante el período de tiempo completo en que ha tenido lugar el adelantamiento, pero es una pista de que se ha ejercido cierta presión de adelantamiento sobre el proceso.
Evalúe el modo en que el proceso determina el número apropiado de subprocesos que deben ejecutarse durante esta fase de trabajo.Si el proceso calcula directamente el número de subprocesos paralelos activos, considere la posibilidad de modificar ese algoritmo para dar cuenta con más exactitud del número de núcleos lógicos disponibles en el sistema.Si utiliza el Runtime de simultaneidad, Task Parallel Library o PLINQ, estas bibliotecas realizan el trabajo de calcular el número de subprocesos.
E/S ineficaz
El exceso o escasez de uso de E/S es una causa habitual de la pérdida de eficacia en las aplicaciones.Observe la ilustración anterior.En el Perfil de escala de tiempo visible se refleja que el 42 por ciento del tiempo de subprocesos visible se usa en operaciones de E/S.La escala de tiempo muestra grandes cantidades de E/S, lo que indica que la aplicación del perfil queda bloqueada habitualmente por operaciones de E/S.Para ver información detallada sobre los tipos de E/S y el lugar donde el programa está bloqueado, amplíe las regiones problemáticas, examine el Perfil de escala de tiempo visible y haga clic en un bloqueo de E/S concreto para ver las pilas de llamadas actuales.
Convoyes de bloqueo
Los convoyes de bloqueo se producen cuando la aplicación adquiere bloqueos en el orden "el primero que llega es el primero que se atiende", y cuando la tasa de llegada en el bloqueo es mayor que la tasa de adquisición.La combinación de estas dos condiciones hace que las solicitudes del bloqueo empiecen a acumularse.Una manera de combatir este problema es usar bloqueos no equitativos o bloqueos que den acceso al primer subproceso para buscar los que tienen un estado desbloqueado.En la ilustración anterior se muestra este comportamiento.Para resolver el problema, intente reducir la contención de los objetos de sincronización e intente usar bloqueos no equitativos.