Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is android's String.format dog slow?

I was implementing a ListView activity with custom drawn views and had the following code:

@Override
public void onDraw(Canvas canvas)
{
    super.onDraw(canvas);
    ....
    canvas.drawText(String.format("%02d: %dx%d", position, w, h),
        10, 15, cached_paint);
}

Pretty much nothing else in the onDraw method, so this was driving me mad as to why the scrolling was so poor. By chance I changed the drawText parameter to not use String.format and suddenly the scrolling was butter silk again. In fact, the following is practically the same yet performs well:

canvas.drawText("" + position + ": " + w + "x" + h,
    10, 15, cached_paint);

I'm stunned. Why is the latter faster than calling String.format? I would expect the object concatenation generate more intermediate objects and in general trash performance, but I've found exactly the opposite. In fact, when running with String.format I was getting lots of allocation/deallocation messages from the vm.

So why is String.format so slow when it apparently could be faster (at least when coming from other programming languages where object creation is expensive)?

like image 676
Grzegorz Adam Hankiewicz Avatar asked Jun 10 '11 20:06

Grzegorz Adam Hankiewicz


2 Answers

String concatenation with + doesn't generate a lot of intermediate objects; basically a StringBuffer and its internal character array (which might get reallocated if it runs out of capacity). Oh, and the String when it's through concatenating.

Also, with +, most of the work of analyzing the data types of the objects going into the string is done at compile time. With String.format, that is done at run time. To top it off, every primitive type you pass to String.format needs to be autoboxed, which does generate a lot more objects.

like image 152
Ted Hopp Avatar answered Oct 06 '22 21:10

Ted Hopp


I'm stunned.

Why?

Why is the latter faster than calling String.format?

Because it is written in Java. %02d: %dx%d is not Java. That has to be parsed every time and the rules executed every time. Those rules are executed in Java, via java.util.Formatter.

Now, String.format() could be optimized by replacing it with a native code (C/C++) implementation, but I think varargs and JNI get messy.

I would expect the object concatenation generate more intermediate objects and in general trash performance, but I've found exactly the opposite. In fact, when running with String.format I was getting lots of allocation/deallocation messages from the vm.

That would be because String.format() is rather complex and is implemented in Java.

like image 36
CommonsWare Avatar answered Oct 06 '22 23:10

CommonsWare