NPE*_*NPE 5 java memory string floating-point performance
所以我有这个Java程序,我用它来咀嚼几兆兆字节的数据.性能是一个问题.
我已经分析了应用程序,并且所有内存分配的大部分以及大部分CPU时间来自执行一个简单的操作:
我有一个ASCII字符数组.我知道从offset i到offset 的字符j代表一个浮点数.我需要将该浮点数提取到一个double.
天真就是Double.parseDouble(new String(buf, i, j - i))这样.但是,这是花费大量时间和大量内存分配的地方,可能是因为:
new String()创建一个新对象,创建一个内部char[]数组并将字符复制到数组中;Double.parseDouble()
创建一个FloatingDecimal对象,并创建一个char[]数组,同时将字符复制到其中.所有这些分配和所有这些复制都不是必需的.我可以避开它们吗?
我真正喜欢的是一个类似于strtod函数的函数,它会接受char[](或byte[])以及开始/结束偏移,并返回一个double.
有什么建议?我应该推出自己的吗?我应该写一个JNI包装器strtod吗?我应该使用一些已经存在的Java库吗?
我过去所做的是为ByteBuffer编写一个解析器(以避免字节到字符编码转换)加倍,反之亦然.如果你可以避免创建任何对象,它可以更快.此方法适用于内存映射文件,从而避免了一些复制成本.
核心代码如下所示.它不处理指数,但你可以添加它.
@Override
public double read() throws BufferUnderflowException {
long value = 0;
int exp = 0;
boolean negative = false;
int decimalPlaces = Integer.MIN_VALUE;
while (true) {
byte ch = buffer.get();
if (ch >= '0' && ch <= '9') {
while (value >= MAX_VALUE_DIVIDE_10) {
value >>>= 1;
exp++;
}
value = value * 10 + (ch - '0');
decimalPlaces++;
} else if (ch == '-') {
negative = true;
} else if (ch == '.') {
decimalPlaces = 0;
} else {
break;
}
}
return asDouble(value, exp, negative, decimalPlaces);
}
Run Code Online (Sandbox Code Playgroud)
一旦它获得任何不期望的字节,它就会停止,例如a ,或\n