我最近使用JSON来存储同一类的一定数量的子类的配置参数。为了保持统一的界面,我为父类提供了公共void setParameter(String, String)
和String getParameter(String)
方法。然后,每个子类将提供的参数转换为其本机类型,并使用它们进行某种计算。
现在,我想知道:因为我已经将每个参数存储在HashMap中,为每个参数保留一个具有正确类型的单独字段是否真的有意义?每次我需要时,将String参数转换为本机类型的计算开销是多少,因为我需要经常使用它们?
谢谢你 Tunnuz
答案 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)
例如,将其更改为每次使用不同的值并将值转储到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.");