Beetl 性能揭秘 1 :如何输出一个整型变量

阅读更多

常规来说,IO流提供了输出字符串(字符数组)的功能,所以,通常的整型输出应该是这样的代码:
String str = String.valueOf(12);
out.write(str);


对于模板引擎来说,输出整形变量很常见,事实上,这个地方有非常大的性能提高空间。我们只要分析这俩句话的源码,就能看出,如何提高io输出int性能。

对于第一句 String.valueOf 实际上调用了Integer.toString(int i) 方法,此方法原代码如下
public static String toString(int i) {
    if (i == Integer.MIN_VALUE)
        return "-2147483648";
    int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
    char[] buf = new char[size];
    getChars(i, size, buf);
    return new String(buf, true);
}


我们注意到,代码第5行分配了一个数组,对于任何一个高效的java工具来说,这都是个告警消息,分配数组耗时,垃圾回收也耗时

我们在分析out.write(str);代码,对于输出一个字符串,必须将字符串先转为字符串数组( 看到问题没有,这又回去了),熟悉String源码的同学都知道,这仍然是一个耗时操作,我们看一下源代码:

public char[] toCharArray() {
    // Cannot use Arrays.copyOf because of class initialization order issues
    char result[] = new char[value.length];
    System.arraycopy(value, 0, result, 0, value.length);
    return result;
}


如上代码,我们又发现了一次分配空间的操作,而且,还有一次字符串拷贝 System.arraycopy,这俩部又成了耗时操作

综合上面代码,我们就会发现,简单的一个int输出,除了基本的算法代码外,居然有俩次字符串的分配,还有一次数组copy。难怪性能低下(性能测试中确实这也是个消耗较多cpu的地方)。那么Beetl是如何改善的?

Beetl提供了一个专门的类IntIOWriter来处理字符串输出,如下关键代码片段:

public static void writeInteger(ByteWriter bw, Integer i) throws IOException
{

    if (i == Integer.MIN_VALUE)
    {
        bw.writeString("-2147483648");
        return;
    }

    int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
    char[] buf = bw.getLocalBuffer().getCharBuffer();
    getChars(i, size, buf);
    bw.writeNumberChars(buf, size);

}


如上代码,首先,我们可以看倒数第三行,并未分配字符素组,而是得到跟当前线程有关的一个char[]
其次,代码最后一行,直接就将此数组输出到IO流了,干净利索

综上所述,常规的输出int方法,除了常规算法外,需要俩次数组分配,和一次字符串拷贝操作。而Beetl则只需要常规算法即可输出,节省了俩次数组分配以及一次字符串copy操作。难怪性能这么好!

你可能感兴趣的:(beetl)