Диагностика разгруженного процессора в рабочем приложении .Net

Эти вещи становятся сложными, и нет простых решений без указания дополнительных аргументов в вашей функции. Если у вас есть ... в обоих plot и legend вызовах, вы получите предупреждения при передаче в legend -специфических аргументов. Например, с помощью:

foo.plot <- function(x,y,...) {
    plot(x,y,...)
    legend("bottomleft", "bar", pch = 1, ...)
}

Вы получаете следующие предупреждения:

> foo.plot(1, 1, xjust = 0.5)
Warning messages:
1: In plot.window(...) : "xjust" is not a graphical parameter
2: In plot.xy(xy, type, ...) : "xjust" is not a graphical parameter
3: In axis(side = side, at = at, labels = labels, ...) :
  "xjust" is not a graphical parameter
4: In axis(side = side, at = at, labels = labels, ...) :
  "xjust" is not a graphical parameter
5: In box(...) : "xjust" is not a graphical parameter
6: In title(...) : "xjust" is not a graphical parameter

Существуют способы обойти эту проблему, см. plot.default и ее локальные функции, определенные как обертки вокруг функции, такие как axis, box и т. д., где у вас есть что-то вроде обертки localPlot(), встроенной функции и вызывать ее, а не plot().

bar.plot <- function(x, y, pch = 1, ...) {
    localPlot <- function(..., legend, fill, border, angle, density,
                          xjust, yjust, x.intersp, y.intersp,
                          text.width, text.col, merge, trace, plot = TRUE, ncol,
                          horiz, title, inset, title.col, box.lwd,
                          box.lty, box.col, pt.bg, pt.cex, pt.lwd) plot(...)
    localPlot(x, y, pch = pch, ...)
    legend(x = "bottomleft", legend = "bar", pch = pch, ...)
}

(Довольно 'plot' аргумент нуждается в по умолчанию вне меня, но он не будет работать, не указывая его по умолчанию TRUE.)

Теперь это работает без предупреждений:

bar.plot(1, 1, xjust = 0.5, title = "foobar", pch = 3)

Как вы будете обрабатывать такие графические параметры, как bty, например, будет зависеть от вас - bty повлияет на тип окна графика и тип окна легенды. Также обратите внимание, что я обработал 'pch' по-другому, потому что, если кто-то использует этот аргумент в вызове bar.plot(), вы будете: i) использовать разные символы в легенде / сюжете, и вы получите предупреждение или ошибку о 'pch' совпадающий дважды.

Как вы можете видеть, это начинает становиться довольно сложным ...


Joris 'Answer предоставляет интересное решение, которое я прокомментировал, напомнил мне аргументы списков управления в таких функциях, как lme(). Вот моя версия Joris 'Ответ, реализующая идею этой идеи контрольного списка:

la.args <- function(x = "bottomleft", legend = "bar", pch = 1, ...)
    c(list(x = x, legend = legend, pch = pch), list(...))

foo.plot <- function(x,y, legend.args = la.args(), ...) {
    plot(x, y, ...)
    do.call(legend, legend.args)
}

Что работает так, используя второй пример вызова Jori, соответствующим образом измененный:

foo.plot(1,1, xaxt = "n", legend.args=la.args(bg = "yellow", title = "legend"))

Вы можете быть настолько полными, насколько вам нравится, когда настраиваете функцию la.args() - здесь я устанавливаю только значения по умолчанию для аргументов Joris, настроенных и объединяющих любые другие. Было бы проще, если бы la.args() содержал все аргументы легенды со значениями по умолчанию.

10
задан Sam Saffron 10 November 2009 в 23:50
поделиться

10 ответов

Базовое решение

  1. Получение управляемых трассировок стека каждого управляемого потока.
  2. Получение базовой статистики потока для каждого управляемого потока (пользователь режим и время ядра)
  3. Немного подождите
  4. Повторите (1-3)
  5. Проанализируйте результаты и найдите потоки, потребляющие наибольшее количество ЦП, представьте пользователю трассировку стека этих потоков.

Управляемый vs. Трассировки стека без привязки

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

managed stack not that useful

Как получить трассировку неуправляемого стека для произвольного. Net process?

Существует два способа получить трассировку управляемого стека для управляемого приложения.

  • Использовать профилирование CLR (также известное как ICorProfiler API)
  • Использовать отладку CLR (также известное как ICorDebug API )

Что лучше в производстве?

API-интерфейсы отладки CLR имеют очень важное преимущество перед профилирующими: они позволяют подключаться к работающему процессу . Это может иметь решающее значение при диагностике проблем с производительностью в производственной среде. Довольно часто неуправляемый процессор выскакивает через несколько дней использования приложения из-за выполнения какой-либо неожиданной ветви кода. В этот момент перезапуск приложения (для его профилирования) невозможен.

cpu-analyzer.exe

Итак, я написал небольшой инструмент без установщика, который выполняет базовое решение, описанное выше, с помощью ICorDebug. Он основан на исходном коде mdbg , который все объединен в один exe.

Требуется настраиваемое (по умолчанию 10) количество трассировок стека для всех управляемых потоков с настраиваемым интервалом (по умолчанию 1000 мс).

Вот пример вывода:

C:\>cpu-analyzer.exe evilapp
------------------------------------
4948
Kernel Time: 0 User Time: 89856576
EvilApp.Program.MisterEvil
EvilApp.Program.b__0
System.Threading.ExecutionContext.Run
System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal
System.Threading._ThreadPoolWaitCallback.PerformWaitCallback

... more data omitted ...

Не стесняйтесь попробовать инструмент. Его можно загрузить из моего блога .

EDIT

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

ИЗМЕНИТЬ

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

ИЗМЕНИТЬ

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

14
ответ дан 3 December 2019 в 16:29
поделиться

A profiler is probably the correct answer here.

If you don't want a "fully fledged profiler" like DotTrace, you might want to try SlimTune. It works fairly well, and is completely free (and open source).

5
ответ дан 3 December 2019 в 16:29
поделиться

Звучит так, будто вам нужен настоящий профилировщик, но я подумал, что просто выброшу его: PerfMon. Он поставляется с окнами, вы можете настроить профиль perfmon, который вы можете отправить пользователю, они могут захватывать и отправлять вам журнал.

Вот пара ссылок, которые я держал каждый раз, когда мне нужно было обновить perfmon: Журнал TechNet от 2008 года и сообщение из блога Advanced .NET Debugging .

2
ответ дан 3 December 2019 в 16:29
поделиться

Мне повезло с профайлером Red Gate Ants . Однако это требует установки. Я почти уверен, что у них нет возможности удаленного управления.

1
ответ дан 3 December 2019 в 16:29
поделиться

Я знаю, что вы конкретно сказали, что не хотите создавать сложные дампы и использовать WinDbg + Sos для их анализа.

Однако в этом нет необходимости. В любом случае я бы предложил использовать WinDbg, но вместо использования дампов просто подключитесь к процессу, когда увидите бегущие потоки. Затем все, что вам нужно сделать, это запустить команду! Runaway. Это даст вам общее время работы для каждого потока. Убегающие потоки будут вверху списка. Теперь все, что вам нужно сделать, это запустить! Clrstack для верхнего потока (или потоков, как это может быть).

Например, если поток 4 является вашим основным подозреваемым, выполните ~ 4e! Clrstack, чтобы получить управляемый стек для этого потока . Это должно сказать вам, что делает беглый поток.

Я согласен, что WinDbg - не самый простой инструмент для многих задач, но на самом деле это может оказаться довольно простым делом, поэтому я надеюсь, что вы простите меня за то, что я опубликовал то, чего вы на самом деле не сделали.

Если о WinDbg все еще не может быть речи, не стесняйтесь комментировать.

1
ответ дан 3 December 2019 в 16:29
поделиться

Используйте управляемый отладчик. Раньше мне помогали. Требуется всего несколько файлов. Вероятно, вы могли бы просто увидеть, что происходит (возможно, обработка исключений застряла в цикле).

1
ответ дан 3 December 2019 в 16:29
поделиться

Используйте SysInternals ProcDump для получения мини-дампа и windbg + sos для его анализа.

Утилита ProcDump доступна здесь: http://technet.microsoft.com/ en-us / sysinternals / dd996900.aspx

Просто отправьте исполняемый файл пользователю и скажите ему, что нужно запустить (например):

ProcDump MyProgram.exe -c 90 -s 10

Это сбросит процесс, если он потребляет более 90% ЦП и более 10 секунды

1
ответ дан 3 December 2019 в 16:29
поделиться

Если вы управляли кодом вместо профилировщика, который стоит использовать, я обнаружил, что добавление сообщения журнала в ваш код чертовски полезно для определения бесконечных циклов и общих многопоточных последовательностей.

т.е.

step 1 msg
step 2 msg

поток теперь 100% и нет сообщения шага 3 = ошибка.

0
ответ дан 3 December 2019 в 16:29
поделиться

Чем хуже проблема, тем легче ее найти с помощью этой техники .

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

0
ответ дан 3 December 2019 в 16:29
поделиться

Я думаю, вам также следует обратить внимание на использование памяти и диска. Если машине не хватает памяти и ей нужно начать использовать виртуальную память (на диске), вы увидите всплеск активности ЦП и диска. В таких условиях то, что кажется узким местом процессора, на самом деле является узким местом памяти.

0
ответ дан 3 December 2019 в 16:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: