Compartir a través de


Seguimiento de un Hog de procesador

Si una aplicación consume ("hogging") toda la atención del procesador, otros procesos acabarán "en hambre" e incapaz de ejecutarse.

Use el procedimiento siguiente para corregir un error de este tipo.

Depuración de una aplicación que usa todos los ciclos de CPU

  1. Identifique qué aplicación está causando este problema: Use el Administrador de tareas o Perfmon para buscar qué proceso usa el 99 % o el 100 % de los ciclos del procesador. Esto puede avisarle también el subproceso infractor.

  2. Adjunte WinDbg, KD o CDB a este proceso.

  3. Identifique qué subproceso está causando el problema: Interrumpa en la aplicación incorrecta. Use la extensión !runaway 3 para tomar una "instantánea" de donde va todo el tiempo de CPU. Use g (Go) y espere unos segundos. A continuación, rompa y use !runaway 3 de nuevo.

    0:002> !runaway 3
     User Mode Time
     Thread    Time
     4e0        0:12:16.0312
     268        0:00:00.0000
     22c        0:00:00.0000
     Kernel Mode Time
     Thread    Time
     4e0        0:00:05.0312
     268        0:00:00.0000
     22c        0:00:00.0000
    
    0:002> g
    
    0:001> !runaway 3
     User Mode Time
     Thread    Time
     4e0        0:12:37.0609
     3d4        0:00:00.0000
     22c        0:00:00.0000
     Kernel Mode Time
     Thread    Time
     4e0        0:00:07.0421
     3d4        0:00:00.0000
     22c        0:00:00.0000
    

    Compare los dos conjuntos de números y busque el subproceso cuyo tiempo de modo de usuario o tiempo del modo kernel ha aumentado más. Dado que !runaway se ordena por tiempo descendente de CPU, el subproceso infractor suele ser el que se encuentra en la parte superior de la lista. En este caso, el subproceso 0x4E0 está causando el problema.

  4. Use los comandos ~ (Estado del subproceso) y ~s (Establecer subproceso actual) para que este sea el subproceso actual:

    0:001> ~
       0  Id: 3f4.3d4 Suspend: 1 Teb: 7ffde000 Unfrozen
    .  1  Id: 3f4.22c Suspend: 1 Teb: 7ffdd000 Unfrozen
     2  Id: 3f4.4e0 Suspend: 1 Teb: 7ffdc000 Unfrozen
    
    0:001> ~2s
    
  5. Use kb (Display Stack Backtrace) para obtener un seguimiento de pila de este subproceso:

    0:002> kb
    FramePtr  RetAddr   Param1   Param2   Param3   Function Name
    0b4ffc74  77f6c600  000000c8.00000000 77fa5ad0 BuggyProgram!CreateMsgFile+0x1b
    0b4ffce4  01836060  0184f440 00000001 0b4ffe20 BuggyProgram!OpenDestFileStream+0xb3
    0b4ffd20  01843eba  02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3
    0b4ffe20  01855924  0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4
    0b4ffe5c  77e112e6  01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34
    0b4ffeb0  77e11215  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0
    0b4ffed0  77e1a3b1  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41
    0b4fff40  77e181e4  02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b
    0b4fff60  77e1a5df  02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91
    0b4fff90  77e1ac1c  77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76
    
  6. Establezca un punto de interrupción en la dirección de retorno de la función que se está ejecutando actualmente. En este caso, la dirección de retorno se muestra en la primera línea como 0x77F6C600. La dirección de retorno es equivalente al desplazamiento de función que se muestra en la segunda línea (BuggyProgram! OpenDestFileStream+0xB3). Si no hay símbolos disponibles para la aplicación, es posible que el nombre de la función no aparezca. Use el comando g (Go) para ejecutarse hasta que se alcance esta dirección de retorno, mediante la dirección simbólica o hexadecimal:

    0:002> g BuggyProgram!OpenDestFileStream+0xb3
    
  7. Si se alcanza este punto de interrupción, repita el proceso. Por ejemplo, supongamos que se alcanza este punto de interrupción. Se deben realizar los pasos siguientes:

    0:002> kb
    FramePtr  RetAddr   Param1   Param2   Param3   Function Name
    0b4ffce4  01836060  0184f440 00000001 0b4ffe20 BuggyProgram!OpenDestFileStream+0xb3
    0b4ffd20  01843eba  02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3
    0b4ffe20  01855924  0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4
    0b4ffe5c  77e112e6  01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34
    0b4ffeb0  77e11215  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0
    0b4ffed0  77e1a3b1  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41
    0b4fff40  77e181e4  02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b
    0b4fff60  77e1a5df  02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91
    0b4fff90  77e1ac1c  77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76
    
    0:002> g BuggyProgram!SaveMsgToDestFolder+0xb3
    

    Si se alcanza, continúe con:

    0:002> kb
    FramePtr  RetAddr   Param1   Param2   Param3   Function Name
    0b4ffd20  01843eba  02b5b920 00000102 02b1e0e0 BuggyProgram!SaveMsgToDestFolder+0xb3
    0b4ffe20  01855924  0b4ffef0 00145970 0b4ffef0 BuggyProgram!DispatchToConn+0xa4
    0b4ffe5c  77e112e6  01843e16 0b4ffef0 0b4fff34 RPCRT4!DispatchToStubInC+0x34
    0b4ffeb0  77e11215  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStubWorker@RPC_INTERFACE@@AAEJPAU_RPC_MESSAGE@@IPAJ@Z+0xb0
    0b4ffed0  77e1a3b1  0b4ffef0 00000000 0b4fff34 RPCRT4!?DispatchToStub@RPC_INTERFACE@@QAEJPAU_RPC_MESSAGE@Z+0x41
    0b4fff40  77e181e4  02b1e0b0 00000074 0b4fff90 RPCRT4!?ReceiveOriginalCall@OSF_SCONNECTION@Z+0x14b
    0b4fff60  77e1a5df  02b1e0b0 00000074 00149210 RPCRT4!?DispatchPacket@OSF_SCONNECTION@+0x91
    0b4fff90  77e1ac1c  77e15eaf 00149210 0b4fffec RPCRT4!?ReceiveLotsaCalls@OSF_ADDRESS@@QAEXXZ+0x76
    
    0:002> g BuggyProgram!DispatchToConn+0xa4
    
  8. Por último, encontrará un punto de interrupción que no se alcanza. En este caso, debe suponer que el último comando g establece el destino en ejecución y no se interrumpa. Esto significa que la función SaveMsgToDestFolder() nunca devolverá.

  9. ¡Vuelva a entrar en el subproceso y establezca un punto de interrupción en BuggyProgram! SaveMsgToDestFolder+0xB3 con el comando bp (Establecer punto de interrupción). A continuación, use el comando g repetidamente. Si este punto de interrupción alcanza inmediatamente, independientemente de cuántas veces haya ejecutado el destino, es muy probable que haya identificado la función infractora:

    0:002> bp BuggyProgram!SaveMsgToDestFolder+0xb3
    
    0:002> g 
    
    0:002> g 
    
  10. Use el comando p (Paso) para continuar con la función hasta que identifique el lugar donde se encuentra la secuencia de bucles de instrucciones. A continuación, puede analizar el código fuente de la aplicación para identificar la causa del subproceso giratorio. La causa suele ser un problema en la lógica de un tiempo, un tiempo, un goto o un bucle for.