Sto lavorando a un progetto che è sia di memoria che di elaborazione intensiva. Una parte significativa dell'esecuzione utilizza il multi-threading con un FixedThreadPool
. In breve; Ho il thread per il recupero dei dati da diverse posizioni remote (utilizzando le connessioni URL) e il popolamento di BlockingQueue
con oggetti da analizzare e n. thread che selezionano questi oggetti ed eseguono l'analisi. edit: vedi codice qui sottoProblemi sporadici nell'esecuzione di un progetto Java multi-thread in Win7
Ora questa configurazione funziona come un fascino sulla mia macchina Linux in esecuzione OpenSUSE 11.3, ma un collega sta testando su una macchina molto simile in esecuzione Win7 è sempre notifiche personalizzate di timeout sulla coda polling (vedi codice sotto), molti di loro in realtà. Ho cercato di monitorare l'utilizzo del processore sulla sua macchina e sembra che il software non occupi più del 15% delle CPU mentre sulla mia macchina l'utilizzo del processore colpisce il tetto, proprio come volevo.
La mia domanda è, quindi, può essere un segno di "fame" della coda? Potrebbe essere che il thread del produttore non stia ottenendo abbastanza tempo CPU? Se sì, come faccio a dare una priorità particolare al thread in piscina?
UPDATE: ho cercato di individuare il problema, senza la gioia ... Ho fatto comunque guadagnare un po 'nuove intuizioni.
Il profilo dell'esecuzione del codice con JVisualVM dimostra un comportamento molto particolare. I metodi sono chiamati in brevi raffiche di CPU-time con diversi secondi di nessun progresso in mezzo. Questo per me significa che in qualche modo il sistema operativo sta colpendo i freni del processo.
Disabilitare l'anti-virus e demoni di back-up non hanno alcun significativo effetto sulla materia
modifica della priorità di java.exe (l'unico caso) attraverso il task manager (avvertita here) non cambia qualcosa. (Detto questo, non potevo dare priorità "realtime" a java, e dovevo accontentarmi di "high" prio)
Il profilo dell'utilizzo della rete mostra un buon flusso di dati in entrata e in uscita, quindi immagino che non è il collo di bottiglia (mentre è una parte considerevole del tempo di esecuzione del processo, ma che conosco già ed è praticamente la stessa percentuale di quello che ottengo sulla mia macchina Linux).
Tutte le idee su come il sistema operativo Win7 potrebbe essere limitante il tempo di CPU per il mio progetto? se non è il sistema operativo, quale potrebbe essere il fattore limitante? Vorrei sottolineare ancora una volta che la macchina NON sta eseguendo nessun altro calcolo intensivo allo stesso tempo e non c'è quasi nessun carico sul CPU diverso dal mio software. Questo mi sta facendo impazzire ...
EDIT: codice rilevante
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);
}
}
La classe QueryingAction
è un semplice Runnable
che chiama il metodo di acquisizione dei dati nel QueryService
oggetto designato che poi popola un BlockingQueue
. La classe AnalysisAction
esegue tutto il numero di crunch per una singola istanza di MyObject
.
Forse il sistema operativo stesso limita le quote di risorse del processo? – fge
potrebbe essere il caso, ma io non sono abbastanza familiare con win7 per verificare se questo è il caso, qualche suggerimento su come controllare che sia il caso ?? – posdef
Quanti thread di consumatori stai utilizzando? Hai provato a ridurre il numero a 1 e aumentarlo gradualmente per vedere come si evolve la situazione? – Tudor