2011-06-10 46 views
4

我正在執行自定義繪製意見的ListView活動,有以下代碼:爲什麼android的String.format狗慢?

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

,沒別的東西在的onDraw方法,所以這是我逼瘋了,爲什麼滾動是如此之差。偶然,我改變了drawText參數,不使用String.format,並且滾動再次是黃油絲。事實上,以下幾乎相同,但表現不錯:

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

我驚呆了。爲什麼後者比調用String.format更快?我期望對象連接產生更多的中間對象和一般的垃圾性能,但我發現恰恰相反。實際上,當使用String.format運行時,我從vm獲取了大量分配/釋放消息。

那麼爲什麼String.format的速度顯然會更快(至少當其他編程語言來自對象創建昂貴時)?

回答

3

字符串與+串聯不會產生大量的中間對象;基本上是一個StringBuffer及其內部字符數組(如果容量不足,可能會重新分配它)。哦,並且通過連接時的字符串。

此外,與+一樣,分析進入字符串的對象的數據類型的大部分工作都是在編譯時完成的。使用String.format,這是在運行時完成的。最重要的是,你傳遞給String.format的每個基本類型都需要自動綁定,這會產生更多的對象。

3

我愣住了。

爲什麼?

爲什麼後者比調用String.format更快?

因爲它是用Java編寫的。 %02d: %dx%d不是Java。每次都必須進行解析,並且每次都執行規則。這些規則在Java中通過java.util.Formatter執行。

現在,String.format()可以通過替換爲本地代碼(C/C++)實現來優化,但我認爲可變參數和JNI會變得混亂。

我希望對象連接生成更多的中間對象和垃圾桶的性能,但我發現恰恰相反。實際上,當使用String.format運行時,我從vm獲取了大量分配/釋放消息。

這將是因爲String.format()是相當複雜,並在Java中實現。

+0

對,只是閱讀一些有關可變參數在java中的性能提示:不要使用它們。 – 2011-06-11 19:41:30

1

爲了獲得最佳性能,您可以從java.text包創建一個格式化程序並將其緩存。

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

爲了獲得更好的性能,可以使用更快的字符串連接。但是,這是一種不同的優化方式,而且這個問題不是主題。