Я пытаюсь выяснить, как правильно использовать исполнителей Java. Я понимаю, что выполнение задач на ExecutorService
имеет свои накладные расходы. Тем не менее, я удивлен, увидев, что он такой высокий, насколько он есть.Исключительная точка безубыточности ExecutorService - эмпирические правила?
Моя программа должна обрабатывать огромное количество данных (данные на фондовом рынке) с минимальной задержкой, насколько это возможно. Большинство вычислений - довольно простые арифметические операции.
Я пытался проверить что-то очень простое: «Math.random() * Math.random()
»
Самый простой тест выполняется это вычисление в простом цикле. Второй тест выполняет одно и то же вычисление внутри анонимного Runnable (это должно измерять стоимость создания новых объектов). Третий тест проходит Runnable
до ExecutorService
(это измеряет стоимость введения исполнителей).
Я побежал испытания на мой изящный ноутбук (2 процессора, 1,5 гиг ОЗУ):
(in milliseconds)
simpleCompuation:47
computationWithObjCreation:62
computationWithObjCreationAndExecutors:422
(примерно один раз из четырех трасс, первые две цифры в конечном итоге равны)
Примечание что исполнители занимают гораздо больше времени, чем выполнение в одном потоке. Цифры были примерно одинаковыми для размеров пулов потоков от 1 до 8.
Вопрос: Я пропустил что-то очевидное или ожидаются ли эти результаты? Эти результаты говорят мне, что любая задача, которую я передаю исполнителю, должна выполнять некоторые нетривиальные вычисления. Если я обрабатываю миллионы сообщений, и мне нужно выполнить очень простые (и дешевые) преобразования для каждого сообщения, я все равно не смогу использовать исполнителей ... попытка распространения вычислений на нескольких процессорах может оказаться дороже, чем просто делая их в одном потоке. Конструктивное решение становится намного сложнее, чем я думал изначально. Есть предположения?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecServicePerformance {
private static int count = 100000;
public static void main(String[] args) throws InterruptedException {
//warmup
simpleCompuation();
computationWithObjCreation();
computationWithObjCreationAndExecutors();
long start = System.currentTimeMillis();
simpleCompuation();
long stop = System.currentTimeMillis();
System.out.println("simpleCompuation:"+(stop-start));
start = System.currentTimeMillis();
computationWithObjCreation();
stop = System.currentTimeMillis();
System.out.println("computationWithObjCreation:"+(stop-start));
start = System.currentTimeMillis();
computationWithObjCreationAndExecutors();
stop = System.currentTimeMillis();
System.out.println("computationWithObjCreationAndExecutors:"+(stop-start));
}
private static void computationWithObjCreation() {
for(int i=0;i<count;i++){
new Runnable(){
@Override
public void run() {
double x = Math.random()*Math.random();
}
}.run();
}
}
private static void simpleCompuation() {
for(int i=0;i<count;i++){
double x = Math.random()*Math.random();
}
}
private static void computationWithObjCreationAndExecutors()
throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(1);
for(int i=0;i<count;i++){
es.submit(new Runnable() {
@Override
public void run() {
double x = Math.random()*Math.random();
}
});
}
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
}
}
Ничего себе, превью форматировал код намного лучше конечного результата. Как я могу это исправить? – Shahbaz
Я просто переформатировал его, посмотрел лучше? –
Спасибо ZZ Coder, код теперь выглядит так, как должно – Shahbaz