avro优化
最近在进行fregata2.0重构时,再次优化avro的反序列化过程。
背景
fregata-quasi任务是典型的cpu和内存都高度消耗的场景,主要是数据的
序列化和反序列化。通过JFR多次观测,其中一个热点是avro中的字符串类型
数据的处理(实际数据中字符串类型出现的比较多,201712的blog也提到过)。
问题源码
对相关代码进行分析后,把目光落在这个区域。
if (length < 0)
throw new AvroRuntimeException("Malformed data. Length is negative: "+ length);
int remaining = limit - pos;
if (length <= remaining) {
System.arraycopy(buf, pos, bytes, start, length);
pos += length;
} else {
// read the rest of the buffer
System.arraycopy(buf, pos, bytes, start, remaining);
start += remaining;
length -= remaining;
pos = limit;
// finish from the byte source
source.readRaw(bytes, start, length);
}
在字符串处理中,Avro引入了一个UTF8对象(本质就是一个byte数组),
在经过这段代码后,再将UTF8对象转为String,经过string的decode。
优化
int start = 0;
int length = readInt();
if (length < 0) {
throw new AvroRuntimeException("Malformed data length : " + length);
}
int remaining = limit - pos;
if (length <= remaining) {
result = new String(buf, pos, length);
pos += length;
} else {
//read the rest of the buffer
result = new String(buf, pos, remaining);
start += remaining;
length -= remaining;
pos = limit;
//finish from the byte source
source.readRaw(null, start, length);
}
这里主要是省掉了中间的UTF8对象,减少了一次System.arraycopy
结论
经过测试,这个优化可以提升10%左右的反序列化速度。