Ограничение числа циклов выполнения сборки - PullRequest
3 голосов
/ 24 октября 2008

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

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

Оптимально я хотел бы указать некоторые полностью загруженные независимые измерения загрузки процессора. При необходимости я могу запускать сборки в своем собственном процессе.

Есть ли способ как-то измерить общее время использования ЦП данного потока (или процесса, хотя поток будет оптимальным)?

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


Чтобы немного экстраполировать мою ситуацию. Причина, по которой я не ищу приоритезацию процессов, заключается в том, что я не боюсь исчерпать свои ресурсы, мне просто нужно убедиться, что я могу измерить «сколько» ресурсов использует данная сборка - таким образом, моя точка зрения о том, что сервер произвольно занят.

Представьте пример сценария, в котором у вас есть две сборки X и Y. Каждая из них реализует определенный алгоритм, и я хочу провести примитивный тест, из которого сборка выполняет работу быстрее всего. Я запускаю каждую сборку и позволяю ей работать до тех пор, пока не будут использованы ресурсы "Z", после чего я оцениваю, какая сборка справилась лучше всего. В этом случае я не против, если одна сборка будет работать на 100% ЦП в течение трех секунд, а другая - на 2% ЦП в течение 5 минут - важно общее использование ресурсов.

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

Ответы [ 3 ]

1 голос
/ 26 октября 2008

Мне любопытно, почему вы думаете, что не можете (не должны) использовать приоритет для этого. Люди в Microsoft потратили очень много времени на разработку планировщика задач, который дает всем потокам / процессам равный шанс на процессор. Если на вашем компьютере запущены процессы с более высоким приоритетом, и вы не хотите, чтобы ваша программа / сторонние библиотеки влияли на эту другую программу, просто установите приоритет ниже этой другой программы, и вы этого не сделаете. Вот для чего приоритет. Даже если ваша программа максимизирует процессор до 100%, эта другая программа будет вытеснять ваш процесс или потоки, когда она захочет работать, даже когда приоритеты равны, но особенно когда у нее более высокий приоритет.

Если вы по-прежнему настроены, то вам придется либо использовать PerformanceCounter , либо Win32 API для мониторинга вашего процесса / потока и использовать Thread.Sleep, когда вы превысите свой порог. Это кажется слишком грязным.

Лучшим вариантом (IMO) является использование настраиваемого пула потоков, который позволяет настраивать максимальное количество потоков, ставить в очередь поток для каждой загружаемой сборки, устанавливать их приоритет на один ниже нормы и контролировать, чтобы определить максимальное количество потоков. темы, которые дают желаемое ограничение производительности. Очень хороший пользовательский пул потоков можно найти здесь . (Пул потоков .NET не позволит вам ограничивать некоторые вещи, поэтому вам нужно использовать пользовательский пул потоков.)


Другой вариант, если вы работаете на компьютере с несколькими процессорами, - это использовать привязку, чтобы ограничить вашу программу определенными ядрами. На четырехъядерном компьютере, если вы ограничите свою программу, например, до core3, то она может пойти наперекосяк и максимально использовать этот процессор, а остальная часть системы будет по-прежнему иметь 3 ядра для поддержания высокой доступности.

1 голос
/ 27 октября 2008

Способ работы большинства операционных систем X86 заключается в использовании вытесняющего планирования потоков. ОС инициализирует таймер на материнской плате, который будет отправлять прерывание процессору каждые, скажем, 100 мс. (Это фрагмент выполнения. Хорошо работающие вычислительные программы обычно должны начинать ожидать чего-то, помещая их в очередь ожидания до этого предела.) Когда процессор получает прерывание, он переключает выполнение на ядро ​​ОС.

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

При "честном" планировании у вас может быть вращающийся менеджер (поскольку вы не заинтересованы в экономии энергии), который просматривает время выполнения соответствующих потоков и завершает их, если они выполнялись слишком долго.

1 голос
/ 25 октября 2008

Мне кажется, я помню, что Terrarium сделал нечто похожее на то, что вы хотите, я предлагаю взглянуть на http://www.codeplex.com/terrarium2.

К сожалению, я не думаю, что у вас есть простой способ сделать это, просто настроив домен приложений, куда вы загружаете библиотеки DLL. Вам, вероятно, придется переопределить то, что делает Terrarium.

...