Why is android String.format song slow?

I implemented a ListView operation with custom images 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); } 

There was almost nothing in the onDraw method, so it drove me crazy about why scrolling was so poor. I accidentally changed the drawText parameter to not use String.format, and suddenly the scroll was oily silk again. In fact, almost everything is the same, but it works well:

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

I am stunned. Why is the latter faster than calling String.format? I would expect that concatenating an object would create more intermediate objects and generally garbage performance, but I found the exact opposite. In fact, when working with String.format, I received a lot of messages about distribution / release from vm.

So why is String.format so slow when it can apparently be faster (at least when switching from other programming languages ​​where creating an object is expensive)?

+4
source share
3 answers

Concatenating strings with + does not create many intermediate objects; basically, a StringBuffer and its internal character array (which can be redistributed if it is exhausted). Oh, and String when it is concatenated.

In addition, with + most of the work of analyzing the data types of objects in a string is performed at compile time. With String.format, which is executed at runtime. To top it all off, every primitive type you pass to String.format must be an autobox that generates a lot more objects.

+3
source

I am stunned.

Why?

Why is the latter faster than calling String.format?

Because it is written in Java. %02d: %dx%d not Java. This needs to be analyzed every time, and the rules are followed every time. These rules are executed in Java through java.util.Formatter .

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

I would expect that concatenating an object would generate more intermediate objects and generally garbage performance, but I found the exact opposite. In fact, when working with String.format, I received a lot of messages about distribution / release from vm.

This would be because String.format() quite complex and implemented in Java.

+3
source

To get maximum performance, you can create a formatter from the java.text package and cache it.

 final static DecimalFormat myFormat = new DecimalFormat("###"); @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); .... canvas.drawText(myFormat.format(w) + "x" + myFormat(h)); } 

For better performance, you can use faster string concatenation. But this is a different kind of optimization and off topic for this question.

+1
source

All Articles