Поделиться через


Отслеживание процессорной совки

Если одно приложение потребляет ("хватать") все внимание процессора, другие процессы в конечном итоге будут "голодать" и не смогут выполняться.

Используйте следующую процедуру, чтобы исправить ошибку такого рода.

Отладка приложения, использующее все циклы ЦП

  1. Определите, какое приложение вызывает эту проблему: Используйте диспетчер задач или Perfmon , чтобы определить, какой процесс использует 99 % или 100 % циклов процессора. Это может сказать вам обижающий поток, а также.

  2. Подключите WinDbg, KD или CDB к этому процессу.

  3. Определите, какой поток вызывает проблему: Войдите в приложение, нарушив его. Используйте расширение !runaway 3, чтобы получить "snapshot", где идет все время ЦП. Используйте g (Go) и подождите несколько секунд. Затем снова войдите и используйте !runaway 3 .

    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
    

    Сравните два набора чисел и найдите поток, время которого в пользовательском режиме или в режиме ядра увеличилось больше всего. Так как !runaway сортирует по убыванию времени ЦП, поток, который вызывает ошибку, обычно находится в верхней части списка. В этом случае проблема возникает из-за 0x4E0 потока.

  4. Используйте команды ~ (состояние потока) и ~s (задать текущий поток), чтобы сделать его текущим потоком:

    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. Используйте kb (Display Stack Backtrace) для получения трассировки стека этого потока:

    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. Задайте точку останова для адреса возвращаемой функции, выполняемой в данный момент. В этом случае обратный адрес отображается в первой строке как 0x77F6C600. Возвращаемый адрес эквивалентен смещению функции, показанной во второй строке (BuggyProgram! OpenDestFileStream+0xB3). Если для приложения нет доступных символов, имя функции может не отображаться. Используйте команду g (Go) для выполнения до достижения этого возвращаемого адреса, используя символьный или шестнадцатеричный адрес:

    0:002> g BuggyProgram!OpenDestFileStream+0xb3
    
  7. Если эта точка останова достигнута, повторите процесс. Например, предположим, что эта точка останова достигнута. Необходимо выполнить следующие действия.

    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
    

    Если это происходит, продолжайте с помощью следующего:

    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. Наконец, вы найдете точку останова, которая не попадает. В этом случае следует предположить, что последняя команда g задает целевой объект и не прерывается. Это означает, что функция SaveMsgToDestFolder() никогда не вернет.

  9. Снова войдите в поток и установите точку останова для BuggyProgram! SaveMsgToDestFolder+0xB3 с помощью команды bp (Задать точку останова). Затем используйте команду g несколько раз. Если эта точка останова достигает немедленно, независимо от того, сколько раз вы выполнили целевой объект, весьма вероятно, что вы определили нарушающую функцию:

    0:002> bp BuggyProgram!SaveMsgToDestFolder+0xb3
    
    0:002> g 
    
    0:002> g 
    
  10. Используйте команду p (Шаг), чтобы продолжить работу с функцией, пока не определите место, где находятся циклы последовательности инструкций. Затем можно проанализировать исходный код приложения, чтобы определить причину вращающегося потока. Причиной обычно оказывается проблема в логике времени, времени выполнения, перехода или цикла for .