time javac Main.java --> 0m1.050s time javac Main.java & javac Main.java --> 0m1.808s time javac Main.java & javac Main.java & javac Main.java --> 0m2.690s time javac Main.java & ... 8 time --> 0m8.309s
Lorsque nous javac
commande javac
en parallèle et à chaque augmentation de la commande javac
~1 sec
est ajoutée pour que toute la commande javac
se termine.
Pourquoi y a-t-il une croissance linéaire du temps?
Est-ce que tout le processus javac
cours d’exécution est impliqué d’une manière ou d’une autre dans les locks
, si oui comment le surmonter pour ne pas avoir une croissance linéaire dans le temps
PS: J’ai essayé ci-dessus sur la single core machine
double core machine
4 core machine
tous ont montré le même comportement.
PS2: environnement RedHat7
, javac 1.7.0_79
Le compilateur Java gère déjà la division de son travail entre les processeurs disponibles, même en ne compilant qu’un seul fichier. Par conséquent, si vous exécutez des instances de compilateur distinctes en parallèle, vous ne pourrez pas obtenir les gains de performances escomptés.
Pour le démontrer, j’ai généré un grand programme java (1 million de lignes, 10 000 méthodes) dans un seul fichier appelé Main1.java
. Puis fait des copies supplémentaires comme Main2.java
par Main8.java
. Les temps de compilation sont les suivants:
Compilation de fichier unique:
time javac Main1.java & --> (real) 11.6 sec
En regardant ce fichier unique comstackr en top
révélé l’utilisation du processeur principalement dans la plage de 200 à 400% (indiquant l’utilisation de plusieurs processeurs, 100% par CPU), avec des pics occasionnels dans la plage de 700% (le maximum sur cette machine est de 800% 8 processeurs).
Ensuite, deux fichiers simultanément:
time javac Main1.java & --> (real) 14.5 sec time javac Main2.java & --> (real) 14.8 sec
Il n’a donc fallu que 14,8 secondes pour en comstackr deux, alors qu’il a fallu 11,6 secondes pour en comstackr une. C’est définitivement non linéaire. En regardant en top
il était clair que chaque compilateur java ne profitait que d’un maximum de quatre processeurs à la fois (avec des pics occasionnels plus élevés). À cause de cela, les deux compilateurs ont couru sur huit processeurs la plupart du temps en parallèle.
Ensuite, quatre fichiers simultanément:
time javac Main1.java & --> (real) 24.2 sec time javac Main2.java & --> (real) 24.6 sec time javac Main3.java & --> (real) 25.0 sec time javac Main4.java & --> (real) 25.0 sec
Ok, ici nous avons frappé le mur. Nous ne pouvons plus paralléliser le compilateur. Quatre fichiers ont pris 25 secondes lorsque deux ont pris 14,8. Il y a une petite optimisation là-bas mais c’est surtout une augmentation de temps linéaire.
Enfin, huit simultanément:
time javac Main1.java & --> (real) 51.9 sec time javac Main2.java & --> (real) 52.3 sec time javac Main3.java & --> (real) 52.5 sec time javac Main4.java & --> (real) 53.0 sec time javac Main5.java & --> (real) 53.4 sec time javac Main6.java & --> (real) 53.5 sec time javac Main7.java & --> (real) 53.6 sec time javac Main8.java & --> (real) 54.6 sec
C’était en fait un peu moins que linéaire, car huit ont pris 54,6 secondes alors que quatre ont seulement pris 25,0 secondes.
Donc, je pense que tout cela consiste à croire que le compilateur fera un travail correct en essayant d’optimiser le travail que vous lui consacrez sur les ressources CPU disponibles, et que tenter d’append de la parallélisation à la main aura un impact limité (le cas échéant). avantage.
Modifier:
Pour référence, il y a deux entrées que j’ai trouvées dans la firebase database de bogues d’Oracle concernant l’amélioration de javac pour tirer parti de plusieurs processeurs: