Theres une bonne écriture sur les Exceptions ici.
http://shipilev.net/blog/2014/exceptional-performance/
La conclusion étant que la trace de la pile de la construction et le déroulement de pile sont les pièces qui coûtent cher. Le code ci-dessous bénéficie d'une fonction en 1.7
où l'on peut tourner les traces de pile sur et en dehors. On peut alors l'utiliser pour voir ce genre de coûts des différents scénarios ont
Voici les horaires pour la création de l'Objet seul. J'ai ajouté String
ici, donc vous pouvez voir que sans la pile étant écrit, il n'y a presque pas de différence dans la création d'un JavaException
Objet et un String
. Avec pile d'écriture activée, la différence est spectaculaire c'est à dire à moins d'un ordre de grandeur inférieur.
Time to create million String objects: 41.41 (ms)
Time to create million JavaException objects with stack: 608.89 (ms)
Time to create million JavaException objects without stack: 43.50 (ms)
Le tableau suivant indique combien de temps il a fallu pour retourner à partir d'une projection à une profondeur d'un million de fois.
|Depth| WriteStack(ms)| !WriteStack(ms)| Diff(%)|
| 16| 1428| 243| 588 (%)|
| 15| 1763| 393| 449 (%)|
| 14| 1746| 390| 448 (%)|
| 13| 1703| 384| 443 (%)|
| 12| 1697| 391| 434 (%)|
| 11| 1707| 410| 416 (%)|
| 10| 1226| 197| 622 (%)|
| 9| 1242| 206| 603 (%)|
| 8| 1251| 207| 604 (%)|
| 7| 1213| 208| 583 (%)|
| 6| 1164| 206| 565 (%)|
| 5| 1134| 205| 553 (%)|
| 4| 1106| 203| 545 (%)|
| 3| 1043| 192| 543 (%)|
La suite est presque certainement une brute sur la simplification...
Si nous prenons une profondeur de 16 ans avec pile de l'écriture puis de la création de l'objet est de l'ordre de ~40% du temps, la trace de la pile représente la grande majorité de ce. ~93% de l'instanciation de la JavaException objet est due à la trace de la pile d'être pris. Cela signifie que le dénouement de la pile dans ce cas est de prendre les autres 50% du temps.
Lorsque nous éteignons la trace de la pile d'objets de création de comptes pour un beaucoup plus petit
fraction, soit 20% et le déroulement de pile représente aujourd'hui 80% du temps.
Dans les deux cas, le déroulement de pile prend une grande partie du temps global.
public class JavaException extends Exception {
JavaException(String reason, int mode) {
super(reason, null, false, false);
}
JavaException(String reason) {
super(reason);
}
public static void main(String[] args) {
int iterations = 1000000;
long create_time_with = 0;
long create_time_without = 0;
long create_string = 0;
for (int i = 0; i < iterations; i++) {
long start = System.nanoTime();
JavaException jex = new JavaException("testing");
long stop = System.nanoTime();
create_time_with += stop - start;
start = System.nanoTime();
JavaException jex2 = new JavaException("testing", 1);
stop = System.nanoTime();
create_time_without += stop - start;
start = System.nanoTime();
String str = new String("testing");
stop = System.nanoTime();
create_string += stop - start;
}
double interval_with = ((double)create_time_with)/1000000;
double interval_without = ((double)create_time_without)/1000000;
double interval_string = ((double)create_string)/1000000;
System.out.printf("Time to create %d String objects: %.2f (ms)\n", iterations, interval_string);
System.out.printf("Time to create %d JavaException objects with stack: %.2f (ms)\n", iterations, interval_with);
System.out.printf("Time to create %d JavaException objects without stack: %.2f (ms)\n", iterations, interval_without);
JavaException jex = new JavaException("testing");
int depth = 14;
int i = depth;
double[] with_stack = new double[20];
double[] without_stack = new double[20];
for(; i > 0 ; --i) {
without_stack[i] = jex.timerLoop(i, iterations, 0)/1000000;
with_stack[i] = jex.timerLoop(i, iterations, 1)/1000000;
}
i = depth;
System.out.printf("|Depth| WriteStack(ms)| !WriteStack(ms)| Diff(%%)|\n");
for(; i > 0 ; --i) {
double ratio = (with_stack[i] / (double) without_stack[i]) * 100;
System.out.printf("|%5d| %14.0f| %15.0f| %2.0f (%%)| \n", i + 2, with_stack[i] , without_stack[i], ratio);
//System.out.printf("%d\t%.2f (ms)\n", i, ratio);
}
}
private int thrower(int i, int mode) throws JavaException {
ExArg.time_start[i] = System.nanoTime();
if(mode == 0) { throw new JavaException("without stack", 1); }
throw new JavaException("with stack");
}
private int catcher1(int i, int mode) throws JavaException{
return this.stack_of_calls(i, mode);
}
private long timerLoop(int depth, int iterations, int mode) {
for (int i = 0; i < iterations; i++) {
try {
this.catcher1(depth, mode);
} catch (JavaException e) {
ExArg.time_accum[depth] += (System.nanoTime() - ExArg.time_start[depth]);
}
}
//long stop = System.nanoTime();
return ExArg.time_accum[depth];
}
private int bad_method14(int i, int mode) throws JavaException {
if(i > 0) { this.thrower(i, mode); }
return i;
}
private int bad_method13(int i, int mode) throws JavaException {
if(i == 13) { this.thrower(i, mode); }
return bad_method14(i,mode);
}
private int bad_method12(int i, int mode) throws JavaException{
if(i == 12) { this.thrower(i, mode); }
return bad_method13(i,mode);
}
private int bad_method11(int i, int mode) throws JavaException{
if(i == 11) { this.thrower(i, mode); }
return bad_method12(i,mode);
}
private int bad_method10(int i, int mode) throws JavaException{
if(i == 10) { this.thrower(i, mode); }
return bad_method11(i,mode);
}
private int bad_method9(int i, int mode) throws JavaException{
if(i == 9) { this.thrower(i, mode); }
return bad_method10(i,mode);
}
private int bad_method8(int i, int mode) throws JavaException{
if(i == 8) { this.thrower(i, mode); }
return bad_method9(i,mode);
}
private int bad_method7(int i, int mode) throws JavaException{
if(i == 7) { this.thrower(i, mode); }
return bad_method8(i,mode);
}
private int bad_method6(int i, int mode) throws JavaException{
if(i == 6) { this.thrower(i, mode); }
return bad_method7(i,mode);
}
private int bad_method5(int i, int mode) throws JavaException{
if(i == 5) { this.thrower(i, mode); }
return bad_method6(i,mode);
}
private int bad_method4(int i, int mode) throws JavaException{
if(i == 4) { this.thrower(i, mode); }
return bad_method5(i,mode);
}
protected int bad_method3(int i, int mode) throws JavaException{
if(i == 3) { this.thrower(i, mode); }
return bad_method4(i,mode);
}
private int bad_method2(int i, int mode) throws JavaException{
if(i == 2) { this.thrower(i, mode); }
return bad_method3(i,mode);
}
private int bad_method1(int i, int mode) throws JavaException{
if(i == 1) { this.thrower(i, mode); }
return bad_method2(i,mode);
}
private int stack_of_calls(int i, int mode) throws JavaException{
if(i == 0) { this.thrower(i, mode); }
return bad_method1(i,mode);
}
}
class ExArg {
public static long[] time_start;
public static long[] time_accum;
static {
time_start = new long[20];
time_accum = new long[20];
};
}
La pile d'images dans cet exemple sont minuscules par rapport à ce que vous trouveriez normalement.
Vous pouvez coup d'oeil au code binaire à l'aide de javap
javap -c -v -constants JavaException.class
ie c'est pour la méthode 4...
protected int bad_method3(int, int) throws JavaException;
flags: ACC_PROTECTED
Code:
stack=3, locals=3, args_size=3
0: iload_1
1: iconst_3
2: if_icmpne 12
5: aload_0
6: iload_1
7: iload_2
8: invokespecial #6 // Method thrower:(II)I
11: pop
12: aload_0
13: iload_1
14: iload_2
15: invokespecial #17 // Method bad_method4:(II)I
18: ireturn
LineNumberTable:
line 63: 0
line 64: 12
StackMapTable: number_of_entries = 1
frame_type = 12 /* same */
Exceptions:
throws JavaException