Donc, ma réponse était juste à plat de mal, parce que mon test a été écrit mal. Je suppose que je suis le seul qui doit avoir été critiqué, pas OP ;) Cela peut avoir été l'un des premiers benchmarks que j'ai jamais écrit... eh bien, c'est la façon dont vous apprenez. Plutôt que de supprimer la réponse, voici les résultats, si je ne suis pas en mesure de quelque chose de mal. Quelques remarques:
- Précalculer les tableaux donc je ne plaisante pas avec les résultats en générant eux
- Ne jamais appeler
BigDecimal.doubleValue()
, comme il est extrêmement lent
- Ne salissez pas avec les résultats en ajoutant
BigDecimal
s. Il suffit de retourner une valeur, et d'utiliser une instruction if pour empêcher l'optimisation du compilateur. Assurez-vous de faire travailler la plupart du temps pour permettre à la branche de prédiction afin d'éliminer la partie du code.
Tests:
- BigDecimal: faites le calcul exactement comme vous l'a suggéré
- BigDecNoRecip: (1/b) * c = c/b, il suffit de faire c/b
- Double: faire le calcul avec des doubles
Voici le résultat:
0% Scenario{vm=java, trial=0, benchmark=Double} 0.34 ns; ?=0.00 ns @ 3 trials
33% Scenario{vm=java, trial=0, benchmark=BigDecimal} 356.03 ns; ?=11.51 ns @ 10 trials
67% Scenario{vm=java, trial=0, benchmark=BigDecNoRecip} 301.91 ns; ?=14.86 ns @ 10 trials
benchmark ns linear runtime
Double 0.335 =
BigDecimal 356.031 ==============================
BigDecNoRecip 301.909 =========================
vm: java
trial: 0
Voici le code:
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Random;
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;
public class BigDecimalTest {
public static class Benchmark1 extends SimpleBenchmark {
private static int ARRAY_SIZE = 131072;
private Random r;
private BigDecimal[][] bigValues = new BigDecimal[3][];
private double[][] doubleValues = new double[3][];
@Override
protected void setUp() throws Exception {
super.setUp();
r = new Random();
for(int i = 0; i < 3; i++) {
bigValues[i] = new BigDecimal[ARRAY_SIZE];
doubleValues[i] = new double[ARRAY_SIZE];
for(int j = 0; j < ARRAY_SIZE; j++) {
doubleValues[i][j] = r.nextDouble() * 1000000;
bigValues[i][j] = BigDecimal.valueOf(doubleValues[i][j]);
}
}
}
public double timeDouble(int reps) {
double returnValue = 0;
for (int i = 0; i < reps; i++) {
double a = doubleValues[0][reps & 131071];
double b = doubleValues[1][reps & 131071];
double c = doubleValues[2][reps & 131071];
double division = a * (1/b) * c;
if((i & 255) == 0) returnValue = division;
}
return returnValue;
}
public BigDecimal timeBigDecimal(int reps) {
BigDecimal returnValue = BigDecimal.ZERO;
for (int i = 0; i < reps; i++) {
BigDecimal a = bigValues[0][reps & 131071];
BigDecimal b = bigValues[1][reps & 131071];
BigDecimal c = bigValues[2][reps & 131071];
BigDecimal division = a.multiply(BigDecimal.ONE.divide(b, MathContext.DECIMAL64).multiply(c));
if((i & 255) == 0) returnValue = division;
}
return returnValue;
}
public BigDecimal timeBigDecNoRecip(int reps) {
BigDecimal returnValue = BigDecimal.ZERO;
for (int i = 0; i < reps; i++) {
BigDecimal a = bigValues[0][reps & 131071];
BigDecimal b = bigValues[1][reps & 131071];
BigDecimal c = bigValues[2][reps & 131071];
BigDecimal division = a.multiply(c.divide(b, MathContext.DECIMAL64));
if((i & 255) == 0) returnValue = division;
}
return returnValue;
}
}
public static void main(String... args) {
Runner.main(Benchmark1.class, new String[0]);
}
}