Инструкции по анализу Spindump?

У меня есть коллекция spindumps, ориентированная на приложение, которое нужно проанализировать, однако я не уверен точно, как их анализировать. Я видел некоторых других разработчиков, которые умеют быстро анализировать их либо мысленно, либо с помощью программного обеспечения, и возвращаться ко мне с подробностями о том, где висят игры, и так далее, и я надеюсь понять, как правильно их анализировать.

Где можно правильно анализировать spindumps?

Ответ 1

Как правило:

  • с сообщением о сбое, вы получите трассировку стека
  • с spindumps, вы получаете несколько следов стека в течение определенного периода времени вместе.

Есть два случая, когда вы можете изучить spindump:

  • бесконечный цикл, возможно, повторяющий одну и ту же функцию снова и снова
  • тупиковый.

Первый случай можно увидеть из spindump многими вызовами одной и той же функции снова и снова. Хорошей вещью для использования в таких ситуациях является Activity Monitor - выберите образец висячего процесса, и вы сможете просмотреть его несколькими полезными способами, спрятать несущественные фреймы и т.д.

Второй случай можно просматривать разными потоками, ожидающими блокировки одновременно.

Вот небольшой пример:

+ 2663 start  (in MyApp) + 52  [0x100001bb4]
+   2663 main  (in MyApp) + 39  [0x100001be7]  main.m:65
+     2663 NSApplicationMain  (in AppKit) + 869  [0x7fff8ea27cb6]
+       2663 -[NSApplication run]  (in AppKit) + 517  [0x7fff8ea83283]
+         2663 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]  (in AppKit) + 128  [0x7fff8ea8bed2]
+           2663 _DPSNextEvent  (in AppKit) + 685  [0x7fff8ea8c613]
+             2663 BlockUntilNextEventMatchingListInMode  (in HIToolbox) + 62  [0x7fff8dd53cd3]
+               2663 ReceiveNextEventCommon  (in HIToolbox) + 356  [0x7fff8dd53e42]
+                 2663 RunCurrentEventLoopInMode  (in HIToolbox) + 209  [0x7fff8dd540a4]
+                   2663 CFRunLoopRunSpecific  (in CoreFoundation) + 290  [0x7fff95dec6b2]
+                     2557 __CFRunLoopRun  (in CoreFoundation) + 1078  [0x7fff95decee6]
+                     ! 2556 __CFRunLoopServiceMachPort  (in CoreFoundation) + 195  [0x7fff95de7803]
+                     ! : 2556 mach_msg  (in libsystem_kernel.dylib) + 70  [0x7fff93630c42]
+                     ! :   2556 mach_msg_trap  (in libsystem_kernel.dylib) + 10  [0x7fff93631686]
+                     ! 1 __CFRunLoopServiceMachPort  (in CoreFoundation) + 199  [0x7fff95de7807]
+                     97 __CFRunLoopRun  (in CoreFoundation) + 728  [0x7fff95decd88]
+                     ! 97 __CFRunLoopDoObservers  (in CoreFoundation) + 369  [0x7fff95e11921]
+                     !   97 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__  (in CoreFoundation) + 23  [0x7fff95e119b7]
+                     !     97 __83-[NSWindow _postWindowNeedsDisplayOrLayoutOrUpdateConstraintsUnlessPostingDisabled]_block_invoke_01208  (in AppKit) + 46  [0x7fff8f05a971]
+                     !       90 _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints  (in AppKit) + 738  [0x7fff8ea8f2ac]
+                     !       : 89 -[NSView displayIfNeeded]  (in AppKit) + 1830  [0x7fff8ea8fd73]

То, что это говорит мне, это то, что MyApp прошел через main и т.д. и, наконец, попал в функцию CFRunLoopRunSpecific, затем __CFRunLoopRun - оттуда (2557) он назвал __CFRunLoopServiceMachPort, который вызвал mach_msg и попал в ловушку в mach_msg_trap (вызов syscall) - когда он вернулся, трассировка стека вернулась в CFRunLoopRunSpecific, где был вызван __CFRunLoopRun, который затем вызывает __CFRunLoopDoObservers и т.д.

Обратите внимание, что это не spindump любого висячего процесса - вы можете проследить этот процесс любым запущенным процессом и посмотреть, какие функции были вызваны во время этого примера. Тем не менее, бесконечный цикл будет повторять вызовы для некоторой функции снова и снова - снова и снова будет одно и то же дерево вызовов. Конечно, это может означать простое для цикла, но это то, где вы можете исследовать, если цикл for не почему-то бесконечен. К сожалению, эти отвалы спина обычно довольно длинные, в зависимости от того, какую функцию вы вызываете, поэтому может потребоваться некоторое время для изучения

Знак + в начале строки просто указывает начало строки - строки без знака + указывают начало нового потока.! и: знаки делают линию, так что вам легче видеть последующие вызовы, т.е. какие вызовы находятся на одном уровне. Далее, | символ также можно использовать.

Цифры означают, сколько времени приложение потрачено на этот конкретный вызов - они находятся в количестве образцов. Сэмплирование работает, что выборочное приложение приостанавливается каждые несколько миллисекунд, и кадр стека исследуется для каждого потока. Если приложение все еще находится в одной и той же функции, функция получает +1.

Ответ 2

Я нашел это при поиске ресурсов для разработчиков Mac для "spindump". Я никогда не видел его, но этот TechNote, упомянутый в справочной странице ReportCrash (8), кажется, показывает вам, как читать журналы сбоев:

https://developer.apple.com/library/mac/#technotes/tn2004/tn2123.html

И ReportCrash (8) ссылался на Spindump (8), мои извинения. https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man8/ReportCrash.8.html

Но, видимо, это не поможет вам. Я тоже останусь здесь.

Надеюсь, что кто-то поможет кому-то.