性能偏执:Float.parseFloat(String),Integer.parseInt(String)多贵?

时间:2011-04-05 08:13:08

标签: java performance interface types casting

我最近使用JSON来存储同一类的一定数量的子类的配置参数。为了保持统一的界面,我为父类提供了公共void setParameter(String, String)String getParameter(String)方法。然后,每个子类将提供的参数转换为其本机类型,并使用它们进行某种计算。

现在,我想知道:因为我已经将每个参数存储在HashMap中,为每个参数保留一个具有正确类型的单独字段是否真的有意义?每次我需要时,将String参数转换为本机类型的计算开销是多少,因为我需要经常使用它们?

谢谢你 Tunnuz

3 个答案:

答案 0 :(得分:5)

我建议你测试一下。如果您需要执行此操作很多次,但是如果您首先使用它们来创建数据,则可能比Double.toString()或Integer.toString()便宜,这是一个相当昂贵的操作。

我还建议你只使用double,除非你知道使用float永远不会导致舍入问题。 ;)

它与创建对象(如String)或向HashMap添加条目一样昂贵。除非你打算避免这样做,否则我不担心。

编辑:类似于@Stackers的基准,我会更长时间地运行测试并使用nanoTime()

int runs = 10000000;
String val = "" + Math.PI;
long start = System.nanoTime();
for (int i = 0; i < runs; i++)
    Float.parseFloat(val);
long time = (System.nanoTime() - start) / runs;
System.out.println("Average Float.parseFloat() time was " + time + " ns.");

long start2 = System.nanoTime();
for (int i = 0; i < runs; i++)
    Double.parseDouble(val);
long time2 = (System.nanoTime() - start2) / runs;
System.out.println("Average Double.parseDouble() time was " + time2 + " ns.");

打印

Average Float.parseFloat() time was 474 ns.
Average Double.parseDouble() time was 431 ns.

顺便说一句:我有从直接ByteBuffer读取双精度的函数,需要80 ns。它更快,因为它不需要String,也不会创建任何对象。但是,执行此操作绝非易事,您必须设计核心系统以避免任何对象创建。 ;)

答案 1 :(得分:3)

衡量就像:

public class PerfTest {
    public static void main(String[] args) {
        String val = "" + (float) Math.PI;
        long start = System.currentTimeMillis();
        for ( int i = 0 ; i < 100000 ; i++ ) {
            Float.parseFloat( val );
        }
        System.out.println( System.currentTimeMillis() - start + " ms." );
    }
}
对于100.000次迭代,

62ms。

答案 2 :(得分:3)

上面的微基准测试看起来有点不安全,你期望热点发现val永远不会发生变化。从未使用过。要记住的另一件事是,有时候(2个实现)的平均值在绝对值上可能会很接近,但是其中1的尾部成本与另一个相比非常差,例如:你的第90个百分位值可能非常相似,但最后10%的情况要差得多。

例如,将其更改为每次使用不同的值并将值转储到stderr会在我的框中产生稍高的平均成本(~3300ns对于重复使用值的情况下为~2500ns)。这比其他帖子要高得多,大概是因为实际花费时间需要花费一些时间,因此测量是人为膨胀的。这只是显示了做一个好的微基准测试的困难之一。

值得注意的是,我无法衡量我建议可能出现的影响,例如:如果它存在,那么你可能会期望它完全被优化掉。如果你非常热衷,我想你可以通过LogCompilation看到发生了什么。

    int runs = 10000000;
    long totalTime = 0;
    for (int i = 0; i < runs; i++) {
        String val = "" + Math.random();
        long start = System.nanoTime();
        float f = Float.parseFloat(val);
        long end = System.nanoTime();
        System.err.println(f);
        totalTime += (end-start);
    }
    long time = totalTime / runs;
    totalTime = 0;
    for (int i = 0; i < runs; i++) {
        String val = "" + Math.random();
        long start = System.nanoTime();
        double d = Double.parseDouble(val);
        long end = System.nanoTime();
        System.err.println(d);
        totalTime += (end-start);
    }
    long time2 = totalTime / runs;
    System.out.println("Average Float.parseFloat() time was " + time + " ns.");
    System.out.println("Average Double.parseDouble() time was " + time2 + " ns.");