2008-10-24 3 views
3

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

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

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

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

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


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

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

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

+0

Являются ли сборки, которые вы загружаете, будут порождаться дочерними процессами? – jmcd 2008-10-24 19:21:47

+0

Нет, детские сборки не будут порождать дочерние процессы. В общем случае дочерние процессы будут запускать очень простой код (сильно ограниченный с использованием CAS). – 2008-10-26 00:57:48

ответ

1

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

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

1

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

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

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


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

1

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

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

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

Смежные вопросы