2013-02-25 2 views
7

Просто интересно, как лучше всего решить, когда прекратить создавать новые потоки на одноядерном компьютере, который работает с той же программой несколько раз, как поток?Оптимизация максимального количества потоков, работающих на ЦПУ

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

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

Любые отзывы о том, какие методы существуют для достижения этого?

Большое спасибо, Владимир

+3

Я думаю, что вы на правильном пути. Следует рассмотреть возможность использования NIO и селекторов, чтобы ваши потоки всегда были заняты, а не всегда ожидали ввода-вывода.Трудно максимизировать пропускную способность, не имея пиков и долин в противном случае. – Gray

+0

Там, Серый избил меня к ней :) С блокировкой ввода-вывода вам понадобится смехотворно большое количество потоков, которые будут тратить оперативную память и больше ничего не делать, кроме как ждать. –

+0

Возможно, вам не захочется создавать темы самостоятельно. Используйте «ExecutorService», который повторно использует потоки для задач «Runnable» или «Callable» и уменьшает накладные расходы на создание разрушающих потоков. –

ответ

1

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

При этом вы можете начать с ThreadPoolExecutor при определенном максимальном количестве потоков (для одного процессора, скажем, 4), а затем проверить каждые 10 секунд или около того среднее значение нагрузки. Если среднее значение нагрузки ниже того, что вы хотите, вы можете позвонить setMaximumPoolSize(...) с большим значением, чтобы увеличить его в течение следующих 10 секунд. Возможно, вам потребуется опросить 30 и более секунд между каждым расчетом, чтобы сгладить производительность вашего приложения.

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

long total = 0; 
    for (long id : threadMxBean.getAllThreadIds()) { 
     long cpuTime = threadMxBean.getThreadCpuTime(id); 
     if (cpuTime > 0) { 
      total += cpuTime; 
     } 
    } 
    // since is in nano-seconds 
    long currentCpuMillis = total/1000000; 

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

Одна вещь, которую следует учитывать, - использовать NIO и селекторов, чтобы ваши потоки всегда были заняты, а не всегда ожидали ввода-вывода. Вот good example tutorial about NIO/Selectors. Вы также можете использовать Pyronet, который, как представляется, предоставляет некоторые полезные функции вокруг NIO.

+0

Мне было интересно. Я нажал на «Pyronet», и у него около 150 скачиваний. Почему бы кто-то включить библиотеку с такой небольшой пользовательской базой, как часть проекта? – Cratylus

+0

Перед тем, как нет альтернативы, и вы не хотите изобретать колесо @Cratylus. :-) – Gray

1

Если async I/O не подходит, я бы рассмотрел использование пулов потоков, например. ThreadPoolExecutor, поэтому у вас нет накладных расходов на создание, уничтожение и воссоздание потоков.

Тогда я бы выполнил тестирование производительности, чтобы настроить максимальное количество потоков, обеспечивая лучшую производительность.

Вы можете начать с 10 потоков, а затем повторить свой тест производительности с 20 потоками, пока вы не нажмете на оптимальное значение. В то же время я хотел бы использовать системные инструменты (в зависимости от вашей ОС) для контроля очереди выполнения потоков, JVM и т. Д.

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

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