7

Tengo una aplicación de Windows Forms con exactamente 2 hilos. Estos subprocesos tienen interacción CERO entre sí, Ala el primer subproceso se ejecuta sin interferir con el segundo subproceso. No hay sincronización entre ellos, ya que no es necesario que eso suceda. El primer hilo trata de la interfaz de usuario de la aplicación, cambiando los colores y las etiquetas, y tiene un temporizador ejecutándose para captar la entrada del usuario. Este temporizador se dispara cada 200 milisegundos. El segundo subproceso está más involucrado y se ejecuta a través de su codificación constantemente hasta que el usuario lo cierre al salir de la aplicación.Visual Studio C# 2010 Express Debug se ejecuta más rápido que la versión

El segundo subproceso lee primero de la memoria y almacena los datos en una lista, luego utiliza estos datos para hacer algunos cálculos. Tengo un temporizador de clase StopWatch para medir el tiempo que lleva completar una iteración del Segundo hilo. Este temporizador se restablece y se inicia al principio del hilo y luego se detiene e imprime en la consola una vez que el hilo ha completado una iteración. Aquí es donde he estado obteniendo mis datos de rendimiento. He estado permitiendo que el subproceso se ejecute durante al menos 1000 iteraciones y luego haciendo un promedio excluyendo la primera ejecución.

La versión de DEPURACIÓN de la compilación, que es la compilación que ejecuta el VSHOST o cuando uno golpea F5 en Visual Studio C# 2010 Express. El promedio de tiempos en 0.00035s es 0.35ms.

Cuando la aplicación se ejecuta fuera de VSHOST, ya sea presionando Ctrl-F5 o ejecutando la aplicación desde el .exe que se produce al presionar BUILD. También utilicé REBUILD para probar esto con un cambio absolutamente CERO. Los tiempos promedio en at365 son 365 ms. Eso es aproximadamente 1000 veces más lento con Release Build.

Estoy completamente enterado de lo que está pasando. ¿Qué está haciendo VSHOST que permite que el programa se ejecute tan rápido? Me he asegurado de que toda la inicialización de la variable sea contabilizada y correcta. Dicho esto, no tengo idea de por qué algo así estaría sucediendo. ¿Alguna idea de por qué estoy obteniendo tal rendimiento?

Como nota al margen, la computadora que estoy usando es 64bit tiene un quad core i7 con Hyper Threading, 16 Gigabytes de RAM y dos HD6750. Por lo tanto, no parece ser una cuestión de tener demasiados hilos, lo único que puede ser un problema es el Hyper Threading.

Un fragmento de código en la forma de lo que hace mi aplicación. Sin embargo, no es posible dar código de trabajo ya que la dirección de la memoria leída es donde ocurre la desaceleración.

namespace Test Snippet 
{ 
public struct Data 
{ 
    public float X; 
    public float Y; 
    public float Z; 
    public float dX; 
    public float dY; 

    public Data(int c) 
    { 
     this.X = ReadFloat(Base + 0x50 + (c * 0x10)); 
     this.Y = ReadFloat(Base + 0x50 + (c * 0x10)); 
     this.Z = ReadFloat(Base + 0x50 + (c * 0x10)); 
     if (this.Z == 1) 
     { 
      targetindex = c; 
     } 
     this.dX = 0; 
     this.dY = 0; 
    } 
} 
class Class1 
{ 
    public int Base = new int(); 
    public List<Data> data = new List<Data>(); 
    public int targetindex = new int(); 
    public Data targetdata = new Data(); 

    public void GetData() 
    { 
     while (true) 
     { 
      data.Clear(); 
      for (int c = 0; c < 64; c++) 
      { 
       Data tempdata = new Data(); 
       teampdata = new Data(c); 
       data.Add(tempdata); 
      } 
      if (data.Count != 0) 
      { 
       targetdata = data[targetindex]; 
       data.RemoveAt(targetindex); 
       targetdata.dX = ReadFloat(Base + 0x66); 
       targetdata.dY = ReadFloat(Base + 0x65); 
       Data[] tempdatarray = new Data[data.Count]; 
       for (int j = 0; j < tempdatarray.Length; j++) 
       { 
        tempdatarray[j].dX = (float)Math.Acos(targetdata.dX * 10); 
        tempdatarray[j].dY = (float)Math.Acos(targetdata.dY * 10); 
       } 
      } 

     } 
    } 
} 

}

EDITAR :: Me han tratado el mismo procedimiento pero sin utilizar el roscado. Tuve la función de hilo llamada por el temporizador que estaba usando para capturar entrada de usuario. Estoy obteniendo los mismos resultados. Entonces eso significa que el enhebrar no parece ser el problema. También hice la prueba en una computadora diferente y por alguna razón no estoy obteniendo la gran diferencia. Lo que me lleva a pensar que puede haber algo mal en mi computadora, o algo relacionado con la forma en que mi procesador maneja los hilos debido a su capacidad Hyper Threading. Alguien sabe si Hyper Threading causa problemas con una aplicación de subprocesos múltiples que no la utiliza explícitamente desde dentro del programa. Que sinceramente no tendría ni idea de cómo configurarlo.

+2

¿Intentó perfilar la aplicación con una herramienta de creación de perfiles real? –

+0

+1 para una pregunta bien investigada y bien escrita – MikeKulls

+0

Es difícil ofrecer asesoramiento sin ningún código para probar. –

Respuesta

1

No veo nada allí para decir que está seleccionando la versión de lanzamiento. Esta es una opción en la barra de herramientas. Si está ejecutando directamente una versión de depuración quizás esté buscando algo que no puede encontrar.

EDIT: excepto el título que me perdí !!!! :-)

+0

Esto es realmente un punto curioso ... y no soy seguro si esto necesariamente tendría un impacto en la conclusión del problema, pero como sugiere @MikeKulls, ** ¿estás seguro de que estás ejecutando la Versión de lanzamiento y potencialmente optimizada del ensamblado?!? ** – fernandoespinosa

+0

Otro punto: Suponiendo que lo anterior no es un problema, ¿su configuración de depuración y su configuración de lanzamiento tienen el mismo objetivo de plataforma? – fernandoespinosa

+0

Sí, he consultado el archivo .csproj y he asegurado que tanto para la versión como para la depuración es la misma plataforma. En cuanto a la configuración que estoy usando, estoy reconstruyendo específicamente el proyecto para cada ejecución y abriendo la depuración configurada, luego se configura la versión. Incluso traté de usar publicar también. Como nota al margen, también he ejecutado la versión de Debug sin el proceso de Host, Ala va a procesar y desmarcar el uso del proceso de host en la depuración. Con los mismos resultados que la versión de lanzamiento. Lo que me lleva a creer que tiene que ver con el Proceso de host. – Nomad101

0

El problema no tiene nada que ver con HyperThreading.No puedo encontrar el enlace, pero hay una buena descripción técnica de 2004 de Intel sobre cómo funciona (sin ninguna exageración de marketing). Pero lo que falta es: Core 0 es probablemente un núcleo real y Core 1 es probablemente un núcleo lógico que comparte el mismo hardware que Core 0. Para nuestra perspectiva (desarrolladores de aplicaciones), los Cores 0 y 1 son reales y no tiene que preocuparse por el hecho de que Core 1 es un núcleo lógico (a excepción de lo obvio, el núcleo lógico solo da un impulso de perf de 13-30% en general, de nuevo se menciona en la descripción técnica). Windows hace un buen trabajo al programar subprocesos en núcleos reales y lógicos. Todo lo que tendría que hacer es crear dos subprocesos, y Windows ejecutaría uno cada uno en los núcleos 0 y 1. Puede deshabilitar HyperThreading en el BIOS, programar afinidad de procesador para sus subprocesos o establecer afinidad desde el Administrador de tareas, si lo desea para experimentar.

Dicho esto, experimentando con HyperThreading no ayudará a resolver su problema. Debe hacer lo que ya se mencionó y perfilar la versión de lanzamiento. También busque errores extraños en el registro de eventos. Y ejecute Process Explorer de sysinternal para ver si se gasta demasiado tiempo en E/S. Quién sabe, tal vez la versión de lanzamiento de alguna manera desencadena un comportamiento peculiar en un controlador de dispositivo en esta máquina.

EDIT: He aquí la descripción de tecnología de Intel (yay Wikipedia), es en realidad de 2002: http://download.intel.com/technology/itj/2002/volume06issue01/vol6iss1_hyper_threading_technology.pdf

1

Así que por primera vez, usted debe hacer algunas perfiles de rendimiento. Use una herramienta de creación de perfiles o simplemente use un temporizador para imprimir algunos mensajes en algún lugar que muestren cuánto tiempo toman ciertas cosas; esto debería permitirle al menos determinar qué línea de código se está ejecutando lentamente aunque no le indique por qué se está ejecutando. mucho más lento debajo del depurador. Sin esta información, todo lo que tienes es conjeturas.

Ahora, en las conjeturas ...

Creo que el problema tiene que ver con el uso de la consola, sobre la base de estas observaciones

  • escrito a la ventana de la consola en sí es en realidad relativamente lento: puede ver esto cuando ejecuta una aplicación que escribe muchas cosas en la consola. Si mantiene la ventana abierta, tardará mucho tiempo en ejecutarse; sin embargo, si minimiza la ventana de la consola, la misma operación puede ejecutar lote más rápido.
  • Según tengo entendido, está escribiendo 1 mensaje en la consola cada 0,35 ms. Eso es un lote de mensajes.
  • Dependiendo de cómo se está ejecutando la aplicación de Visual Studio vuelve a dirigir efectivamente la salida de la consola a la "salida" de la ventana dentro de Visual Studo al depurar.

Supongo que la ventana de la consola en Visual Studio es mucho más rápida que el mecanismo equivalente utilizado cuando no se está depurando, y que la causa de la ralentización adicional es en realidad su código de registro. Intente sacar el registro basado en la consola y regístrese en un archivo para ver si hace alguna diferencia, o incluso simplemente reduzca la cantidad de veces que registra mensajes, p. Ej. registre el tiempo que lleva completar 100 iteraciones; esto reducirá el impacto (si lo hay) que la consola está teniendo en su desempeño.

Cuestiones relacionadas