ExecutorService: le seuil de rentabilité surprenant des performances - règles empiriques?

Je suis à essayer de comprendre comment utiliser correctement Java Exécuteurs testamentaires. Je me rends compte de la soumission de tâches à une ExecutorService a ses propres généraux. Cependant, je suis surpris de voir qu'il est aussi élevé qu'il l'est.

Mon programme doit traiter d'énormes quantités de données (données boursières) avec un temps de latence faible que possible. La plupart des calculs sont assez simples opérations arithmétiques.

J'ai essayé de tester quelque chose de très simple: "Math.random() * Math.random()"

Le test le plus simple ce calcul s'exécute dans une boucle simple. La deuxième épreuve a fait le même calcul à l'intérieur d'un anonyme Exécutable (c'est censé mesurer le coût de la création de nouveaux objets). Le troisième test passe le Runnable à un ExecutorService (cette mesure le coût de l'instauration d'exécuteurs testamentaires).

J'ai couru les tests sur mes dinky ordinateur portable (2 processeurs), 1.5 go de ram):

(in milliseconds)
simpleCompuation:47
computationWithObjCreation:62
computationWithObjCreationAndExecutors:422

(environ une fois sur quatre pistes, les deux premiers numéros de la fin de l'égalité)

Avis que les exécuteurs de prendre beaucoup plus de temps que l'exécution sur un seul thread. Les chiffres étaient à peu près de même pour le pool de thread des tailles comprises entre 1 et 8.

Question: Suis-je raté quelque chose d'évident ou ce sont les résultats attendus? Ces résultats me dire que toute tâche je passe à un exécuteur testamentaire doit faire quelques non-trivial de calcul. Si je suis le traitement de millions de messages, et j'ai besoin d'effectuer de très simple (et bon marché) des transformations sur chaque message, je risque de ne pas être en mesure d'utiliser les exécuteurs...en essayant de propagation des calculs sur plusieurs Processeurs pourrait être plus coûteux de le faire simplement dans un seul thread. La conception de décision devient beaucoup plus complexe que ce que j'avais pensé à l'origine. Toutes les pensées?


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);
}
}

source d'informationauteur Shahbaz