java - 为什么相加解析的 double 比在 Java 中使用 BigDecimal 慢?

标签 java performance performance-testing

为什么

  • result += Double.parseDouble(numberAsString)

result 是一个double 原语,比

  • result = result.add(new BigDecimal(numberAsStrings))

resultBigDecimal

基准:

@Setup
public void beforeEach() {
    numbersAsStrings = new String[NUMBER_COUNT];
    double currentNumber = 1;
    for (int i = 0; i < NUMBER_COUNT; i++) {
        numbersAsStrings[i] = String.valueOf(currentNumber);
        currentNumber += 0.1;
    }
}

@Benchmark
public double addUpDoublesParsedFromString() {
    double result = 0;
    for (int i = 0; i < numbersAsStrings.length; i++) {
        result += Double.parseDouble(numbersAsStrings[i]);
    }
    return result;
}

@Benchmark
public BigDecimal addUpBigDecimalsFromString() {
    BigDecimal result = new BigDecimal(0);
    for (int i = 0; i < numbersAsStrings.length; i++) {
         result = result.add(new BigDecimal(numbersAsStrings[i]));
    }
    return result;
}

由于基元通常比非基元具有计算速度更快的声誉,因此结果令人惊讶(至少对我而言):

Benchmark                                                   Mode  Samples      Score  Score error  Units

t.n.b.n.BigDecimalVsDouble.addUpDoublesParsedFromString    thrpt        4    484.070       59.905  ops/s
t.n.b.n.BigDecimalVsDouble.addUpBigDecimalsFromString      thrpt        4   1024.567      170.329  ops/s

对于 BigDecimals 的加法是 1024.567 ops/s,但使用基元的加法只有 484.070 ops/s(在 JMH 中进行了基准测试)。

为什么会这样?如果有一种方法可以优化从字符串解析的 double 基元的添加,超出 BigDecimal 的速度,请将其包含在您的答案中。

最佳答案

您实际上在做两件事。 PARSING 和 ADDING,但你指责原始加法速度较慢 [如果你真的剖析了你最初的问题和你的评论,“因为原始人通常比非原始人有计算速度更快的声誉,结果是惊人的(至少对我来说是这样) ):"]。

也许加法运算不是 double 运算的慢运算。也许对基元的解析速度较慢,而基元的添加速度更快。我会尝试更多基准测试,如下所示

double[] doubleValues;
BigDecimal[] bdValues;

@Setup
public void beforeEach() {
    numbersAsStrings = new String[NUMBER_COUNT];
    doubleValues = new double[NUMBER_COUNT];
    bdValues = new BigDecimal[NUMBER_COUNT]; 
    double currentNumber = 1;
    for (int i = 0; i < NUMBER_COUNT; i++) {
        numbersAsStrings[i] = String.valueOf(currentNumber);
        doubleValues[i] = Double.parseDouble(numbersAsStrings[i]);
        bdValues[i] = new BigDecimal(numbersAsStrings[i]);
        currentNumber += 0.1;
    }
}




//additional benchmarks

@Benchmark
public double addUpDoubles() {
    double result = 0;
    for (int i = 0; i < numbersAsStrings.length; i++) {
        result += doubleValues[i];
    }
    return result;
}

@Benchmark
public BigDecimal addUpBigDecimals() {
    BigDecimal result = new BigDecimal(0);
    for (int i = 0; i < numbersAsStrings.length; i++) {
         result = result.add(bdValues[i]);
    }
    return result;
}

@Benchmark
public void doublesParsedFromString() {
    for (int i = 0; i < numbersAsStrings.length; i++) {
        Double d = Double.parseDouble(numbersAsStrings[i]);
    }
}

@Benchmark
public void bigDecimalsParsedFromString() {
    for (int i = 0; i < numbersAsStrings.length; i++) {
         BigDecimal bd = new BigDecimal(numbersAsStrings[i]);
    }
}



//original benchmarks-----------------------

@Benchmark
public double addUpDoublesParsedFromString() {
    double result = 0;
    for (int i = 0; i < numbersAsStrings.length; i++) {
        result += Double.parseDouble(numbersAsStrings[i]);
    }
    return result;
}

@Benchmark
public BigDecimal addUpBigDecimalsFromString() {
    BigDecimal result = new BigDecimal(0);
    for (int i = 0; i < numbersAsStrings.length; i++) {
         result = result.add(new BigDecimal(numbersAsStrings[i]));
    }
    return result;
}

还要考虑这样一种可能性,即较短的数字可能会为 BigDecimal 快速解析,而较长的数字可能不会。我会尝试使用不同的数字范围进行基准测试

关于java - 为什么相加解析的 double 比在 Java 中使用 BigDecimal 慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50733645/

相关文章:

java - 在 apache flink 中反序列化 protobuf 事件中的事件时出现问题

java - 在 Java/印度编号系统中格式化数字

java - 导入 keystore 以签署小程序

Linux Webserver - htop 显示极端的 cpu 使用率?

cocoa-touch - 增量添加到 UIView

hadoop - 与本地文件系统相比,序列文件是否有助于提高 HDFS 的读取性能?

java - 检查 Java : which is the best method? 中的集合是否为空

java - android gmail 应用程序,如 ListView ,图标中有 4 个图标

java - 性能问题 : "java.text.MessageFormat.format" vs "StringBuilder"

android - 如何以受控方式模拟 Android 手机的电池消耗?