Подтвердить что ты не робот

Сколько потоков использовать?

Я знаю, что есть некоторые существующие вопросы, и они дают очень хорошую общую точку зрения на вещи. Я надеюсь получить некоторые детали на стороне С#/VB.Net для фактической реализации (а не философии) некоторых из этих перспектив.

Мой частный случай

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

Для каждого полученного файла (который максимум может быть тысячами в секунду) службе необходимо работать с файлами в течение 1-10 секунд (каждый) в зависимости от ряда других служб, локальных ресурсов и ожидания ввода-вывода в сети раз.

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

Возрастная проблема

Сколько потоков должно быть на пике? Ясно, что добавление нового потока каждый раз, когда был получен файл, было бы глупо из-за отсутствия лучшего слова - производительность в лучшем случае ухудшилась бы. Увязка потоков, когда загрузка процессора составляет всего 10% в каждом ядре, также не представляется лучшим использованием ресурсов.

Итак, есть ли подходящий способ определить, сколько потоков будет закрыто? Я бы предпочел, чтобы служба могла определить это для себя, взяв выборку доступных ресурсов, но есть ли у вас успех? Я знаю, что общий ответ - контролировать рабочие нагрузки, корректировать подсчеты через пробную версию и ошибку до тех пор, пока я не найду номер, который мне нравится, но из-за характера этой услуги (длительные периоды простоя, за которыми следуют высокие/пакетные рабочие нагрузки) это может занять длительное время чтобы получить такую ​​информацию.

Что тогда, если мы переместим изображение сервера на другой хост, который быстрее/медленнее/отличается от первого? Мне нужно снова просмотреть процесс снова?

В идеале, что мне нужно, координатор должен разумно увеличить размер потока thread до тех пор, пока загрузка процессора не будет равна x% (будет ли 80% разумнее? 90%? 99%?). Понятно, что я хочу сделать это, не добавляя больше потоков, чем нужно, чтобы попасть в x%, в противном случае все, что я закончил, это потоки, которые не только ждут ресурсов IO, но и ждут друг друга.

Спасибо заранее!


Связанные вопросы (если вы хотите получить некоторые общие идеи):

Сколько потоков для создания?

Сколько потоков слишком много?

Сколько потоков для создания и когда?


Усложнение для вас

Где было бы весело, если бы я не затруднил проблему?

Как и в настоящее время, эта услуга часто набирает 100% процессор во время этих всплесков. Проблема заключается в загрузке процессора. Он переходит из режима ожидания (0-10%) в 100% и возвращается обратно. Я не уверен, что смогу это помочь - в идеале я бы не дошел до 100%. Проблема возникает из-за того, что упомянутые файлы фактически являются изображениями, а часть процесса сервисов - передать изображение в ящик BlackBox System.Windows.Media, который выполняет некоторую сложную обработку изображений для меня.

Затем происходит затишье между шипами из-за ожиданий IO и другой обработки, которая продолжается. Если спайки, ударяющие на 100%, не могут быть помогли (и я все знаю, как это предотвратить, или если я должен), как я должен стремиться к графику использования ЦП? Сб постоянно на 100%? Отскок между 50-100? Если я попытаюсь выполнить выборку, чтобы решить, что лучше всего работает, гарантировано ли, что переключение хоста виртуальных серверов также будет работать лучше всего с тем же графиком?

Эта дополнительная сложность я не буду принимать во внимание, если вы готовы ответить. Не стесняйтесь игнорировать этот раздел. Тем не менее, любой ответ, который также объясняет это осложнение, или даже ответы, которые просто дают советы о том, как с ним обращаться, я, по крайней мере, вернусь!

Чрез долгий вопрос - извините за это - и спасибо за чтение так много!

4b9b3361

Ответ 1

PerformanceCounter позволяет запрашивать использование процессора.

Однако, вы пробовали что-то, что предоставляет инфраструктура?

        foreach (var file in files)
        {
            var workitem = file;
            Task.Factory.StartNew(() =>
            {
                // do work on workitem
            }, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
        }

Вы можете настроить уровень concurrency для Заданий в Задаче. Factory.

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

Возможно, вам нужно специальное решение, но было бы неплохо сравнить ваши стандарты со стандартом.

Изменить: (примечание к примечанию):

Никаких ссылок не было, я, возможно, использовал выдуманный термин, так как английский не мой язык. Я имею в виду: есть переменная, в которой вы сохраняете дисперсию до последней проверки (prevDelta), и называете ее delta. добавьте это в varaiable avrageDelta и разделите на 2, каждый раз, когда вы "проверяете". У вас будет переменная averageDelta, которая будет в основном низкой, поскольку у вас нет активности. Затем добавьте еще один набор дельта-переменных, один из которых вы уже (delta-prevdelta), и сохраните его в переменной дельты, которая не является средним значением всех дельт, а средняя дельта в небольшом промежутке времени (вам придется придумать algortihm, чтобы точно рассчитать эту временную дисперсию). После этого вы можете сравнить среднюю дельту и "временную дельту". Средняя дельта будет в основном низкой и будет медленно подниматься. В тот же период временная дельта будет расти очень быстро. Тогда у вас есть ситуация, когда разрыв останавливается, средняя дельта идет медленно вниз, а "временная" идет очень быстро.

Ответ 2

Вы можете использовать I/O Completion Ports, чтобы асинхронно извлекать ваши изображения, не связывая нити, пока не наступит время, чтобы обработать то, что вы получили.

Затем вы можете ограничить пул потоков на основе количества ядер на вашем клиентском ПК, оставив ядро ​​свободным для других процессов.

Ответ 3

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