Pregunta

Tenemos un código base que tiene varios años y todos los desarrolladores originales ya no están.Utiliza muchos, muchos hilos, pero sin un diseño aparente ni principios arquitectónicos comunes.Cada desarrollador tenía su propio estilo de programación multiproceso, por lo que algunos subprocesos se comunican entre sí mediante colas, algunos bloquean datos con mutex, algunos bloquean con semáforos y algunos utilizan mecanismos IPC del sistema operativo para las comunicaciones dentro del proceso.No hay documentación de diseño y los comentarios son escasos.Es un desastre y parece que cada vez que intentamos refactorizar el código o agregar nuevas funciones, introducimos puntos muertos u otros problemas.

Entonces, ¿alguien conoce alguna herramienta o técnica que ayudaría a analizar y documentar todas las interacciones entre subprocesos?FWIW, el código base es C++ en Linux, pero me interesaría conocer herramientas para otros entornos.


Actualizar

Aprecio las respuestas recibidas hasta ahora, pero esperaba algo más sofisticado o sistemático que el consejo que es esencialmente "Agregar mensajes de registro, descubrir qué está sucediendo y solucionarlo". Existen muchas herramientas para analizar y documentar el flujo de control en programas de un solo subproceso;¿No hay nada disponible para programas multiproceso?


Ver también Depuración de aplicaciones multiproceso

¿Fue útil?

Solución

Invierta en una copia de Intel VTune y sus herramientas de perfilado de hilos.Le brindará una vista a nivel de sistema y de fuente del comportamiento del hilo.Ciertamente no documentará automáticamente el problema, pero debería ser de gran ayuda al menos para visualizar lo que está sucediendo en diferentes circunstancias.

Creo que hay una versión de prueba que puedes descargar, así que puede que valga la pena intentarlo.Solo he usado la versión de Windows, pero mirando la página web de VTune también tiene una versión de Linux.

Otros consejos

Como punto de partida, estaría tentado a agregar mensajes de registro de seguimiento en puntos estratégicos dentro de su aplicación.Esto le permitirá analizar cómo interactúan sus subprocesos sin peligro de que el acto de observar los subprocesos cambie su comportamiento (como podría ser el caso con la depuración paso a paso).Mi experiencia es con la plataforma .NET y mi herramienta de registro favorita sería log4net, ya que es gratuita, tiene amplias opciones de configuración y, si es sensato a la hora de implementar su registro, no obstaculizará notablemente el rendimiento de su aplicación.Alternativamente, existe la clase Debug (o Trace) integrada de .NET en el espacio de nombres System.Diagnostics.

Primero me centraría en los bloqueos de memoria compartida (los mutex y los semáforos), ya que es más probable que causen problemas.Mire qué estado está protegido por bloqueos y luego determine qué estado está bajo la protección de varios bloqueos.Esto le dará una idea de los conflictos potenciales.Observe situaciones en las que el código que mantiene un bloqueo llama a métodos (no olvide los métodos virtuales).Intente eliminar estas llamadas siempre que sea posible (reduciendo el tiempo que se mantiene el bloqueo).

Dada la lista de mutex que se mantienen y una idea aproximada del estado que protegen, asigne un orden de bloqueo (es decir, el mutex A siempre debe tomarse antes del mutex B).Intente hacer cumplir esto en el código.

Vea si puede combinar varios bloqueos en uno si la simultaneidad no se ve afectada negativamente.Por ejemplo, si parece que los mutex A y B podrían tener interbloqueos y no es fácil realizar un esquema de ordenación, combínelos inicialmente en un solo bloqueo.

No será fácil, pero estoy a favor de simplificar el código a expensas de la concurrencia para solucionar el problema.

Este es un problema realmente difícil para las herramientas automatizadas.Quizás quieras investigar control de modelo tu codigo.No esperes resultados mágicos:Los verificadores de modelos están muy limitados en la cantidad de código y la cantidad de subprocesos que pueden verificar de manera efectiva.

Una herramienta que podría funcionar para usted es AJEDREZ (aunque lamentablemente es sólo para Windows). EXPLOSIÓN es otra herramienta bastante poderosa, pero es muy difícil de usar y es posible que no maneje C++.Wikipedia también enumera Vapor, del que no había oído hablar antes, pero parece que podría funcionar para ti:

StEAM es un verificador de modelos para C++.Detecta interbloqueos, fallas de segmentación, variables fuera de rango y bucles sin terminación.

Alternativamente, probablemente sería de gran ayuda intentar hacer converger el código hacia un pequeño número de esquemas de sincronización bien definidos (y, preferiblemente, de alto nivel).Mezclar bloqueos, semáforos y monitores en la misma base de código genera problemas.

Una cosa a tener en cuenta al usar log4net o una herramienta similar es que cambian el tiempo de la aplicación y, a menudo, pueden ocultar las condiciones de carrera subyacentes.Teníamos un código mal escrito para depurar e introdujimos el registro y esto realmente eliminó las condiciones de carrera y los puntos muertos (o redujo en gran medida su frecuencia).

En Java, tiene opciones como FindBugs (para análisis de código de bytes estático) para encontrar ciertos tipos de sincronización inconsistente, o los muchos analizadores de subprocesos dinámicos de compañías como Coverity, JProbe, OptimizeIt, etc.

¿No puede UML ayudarte aquí?

Si aplica ingeniería inversa a su código base en UML, entonces deberías poder dibujar diagramas de clases que muestren las relaciones entre tus clases.A partir de las clases cuyos métodos son los puntos de entrada del subproceso, puede ver qué subproceso usa qué clase.Basado en mi experiencia con Rosa racional, esto podría lograrse usando arrastrar y soltar;Si no hay relación entre la clase agregada y las anteriores, entonces la clase agregada no es utilizada directamente por el hilo que comenzó con el método con el que comenzó el diagrama.Esto debería darle pistas sobre el papel de cada hilo.

Esto también mostrará los "objetos de datos" que se comparten y los objetos que son específicos del hilo.

Si dibuja un diagrama de clases grande y elimina todos los "objetos de datos", entonces debería poder diseñar ese diagrama como nubes, siendo cada nube un hilo, o un grupo de hilos, a menos que el acoplamiento y la cohesión del código base sean horrible.

Esto sólo te dará una parte del rompecabezas, pero podría ser útil;Sólo espero que su código base no sea demasiado confuso o demasiado "procedimental", en cuyo caso...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top