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)?
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.