Я работаю над проектом, который требует много памяти и вычислительных ресурсов. Значительная часть выполнения использует многопоточность на FixedThreadPool
. Короче; У меня есть поток 1 для извлечения данных из нескольких удаленных местоположений (с использованием URL-соединений) и заполнения BlockingQueue
объектами для анализа и потоками n , которые выбирают эти объекты и запускают анализ , изменить: см. Код ниже
Теперь эта установка работает как чудо на моей машине с Linux, работающей с OpenSUSE 11.3, но коллега, тестирующий ее на очень похожей машине с Win7, получает пользовательских уведомлений о тайм-аутах при опросе очереди (см. Код ниже), их много на самом деле. Я пытался отслеживать использование процессора на ее компьютере, и кажется, что программное обеспечение не получает больше 15% процессоров, в то время как на моей машине загрузка процессора достигает предела, как я и предполагал.
Тогда мой вопрос: может ли это быть признаком "голодания" очереди? Может ли быть так, что поток производителя не получает достаточно процессорного времени? Если да, как мне дать одному конкретному потоку в пуле более высокий приоритет?
UPDATE:
Я пытался определить проблему, не испытывая радости ... Я, однако, получил некоторые новые идеи.
Профилирование выполнения кода с помощью JVisualVM демонстрирует очень своеобразное поведение. Методы вызываются короткими пакетами процессорного времени с интервалом в несколько секунд без прогресса. Для меня это означает, что каким-то образом ОС тормозит процесс.
Отключение антивируса и резервных демонов не оказывает существенного влияния на этот вопрос
Изменение приоритета java.exe (единственный экземпляр) через диспетчер задач (рекомендуется здесь ) также ничего не меняет. (Это, как говорится, я не мог дать приоритет в реальном времени для Java, и должен был довольствоваться "высоким" prio)
Профилирование использования сети показывает хороший поток данных, входящий и выходящий, поэтому я предполагаю, что это не является узким местом (хотя это значительная часть времени выполнения процесса, но это я уже знаю и почти такой же процент, как у моего компьютера с Linux).
Есть идеи, как ОС Win7 может ограничивать время процессора моим проектом? если это не ОС, что может быть ограничивающим фактором? Я хотел бы еще раз подчеркнуть, что на машине НЕ выполняются никакие другие интенсивные вычисления в одно и то же время, и нагрузка на процессор, кроме моего программного обеспечения, почти отсутствует. Это сводит меня с ума ...
РЕДАКТИРОВАТЬ: соответствующий код
public ConcurrencyService(Dataset d, QueryService qserv, Set<MyObject> s){
timeout = 3;
this.qs = qserv;
this.bq = qs.getQueue();
this.ds = d;
this.analyzedObjects = s;
this.drc = DebugRoutineContainer.getInstance();
this.started = false;
int nbrOfProcs = Runtime.getRuntime().availableProcessors();
poolSize = nbrOfProcs;
pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(poolSize);
drc.setScoreLogStream(new PrintStream(qs.getScoreLogFile()));
}
public void serve() throws InterruptedException {
try {
this.ds.initDataset();
this.started = true;
pool.execute(new QueryingAction(qs));
for(;;){
MyObject p = bq.poll(timeout, TimeUnit.MINUTES);
if(p != null){
if (p.getId().equals("0"))
break;
pool.submit(new AnalysisAction(ds, p, analyzedObjects, qs.getKnownAssocs()));
}else
drc.log("Timed out while waiting for an object...");
}
} catch (Exception ex) {
ex.printStackTrace();
String exit_msg = "Unexpected error in core analysis, terminating execution!";
}finally{
drc.log("--DEBUG: Termination criteria found, shutdown initiated..");
drc.getMemoryInfo(true); // dump meminfo to log
pool.shutdown();
int mins = 2;
int nCores = poolSize;
long totalTasks = pool.getTaskCount(),
compTasks = pool.getCompletedTaskCount(),
tasksRemaining = totalTasks - compTasks,
timeout = mins * tasksRemaining / nCores;
drc.log("--DEBUG: Shutdown commenced, thread pool will terminate once all objects are processed, " +
"or will timeout in : " + timeout + " minutes... \n" + compTasks + " of " + (totalTasks -1) +
" objects have been analyzed so far, " + "mean process time is: " +
drc.getMeanProcTimeAsString() + " milliseconds.");
pool.awaitTermination(timeout, TimeUnit.MINUTES);
}
}
Класс QueryingAction
- это простой Runnable
, который вызывает метод сбора данных в обозначенном объекте QueryService
, который затем заполняет BlockingQueue
. Класс AnalysisAction
выполняет все вычисления чисел для одного экземпляра MyObject
.