2013-02-02 58 views
4

我在onDraw()方法的調用堆棧中有3個級別向下的方法。它被稱爲數百次,有時每次重繪數千次。我已經做了onDraw()方法的廣泛分析,我可以看到下面的方法佔總數的14%,所以絕對值得一看。我需要在捏縮放和拖動操作期間獲得幀率。使用局部變量與字段對GC的影響

private void getVisiblePointsFromPath(){ 

    double longRads = longitude * (Math.PI/180); 
    double latRads = latitude * (Math.PI/180); 

    ... 

} 

當方法退出,雙打走出去的範圍,我認爲他們有資格GC,雖然我承認,當這件事會發生具有不確定性。

有什麼用這樣獲得:

public class GisView extends ImageView{ 

    private double longRads; 
    private double latRads; 

    private void getVisiblePointsFromPath(){ 

     longRads = longitude * (Math.PI/180); 
     latRads = latitude * (Math.PI/180); 

     ... 

    } 

} 

我認爲這個成語會導致被清零,然後重新分配在每次通過雙打,但不會導致額外的垃圾,從而減少量我正在造成的GC。還是虛擬機比這更聰明?

請注意,我的問題本身並不是「哪個更快」,而是關於哪個可能導致更少的GC。我可以測量速度差異,但我不太瞭解Dalvik VM和Android GC來預測哪些會導致更少的垃圾。

+4

您應該考慮只計算'Math.PI/180'一次並將其存儲在常量中。 – MrSmith42

+0

@ MrSmith42 Huh。我認爲編譯器會照顧到這一點。當然,由於Math.PI和180是不變的,所以編譯器會使用'= latitude * 0.0174532925' – Simon

+0

我認爲它可能會被優化,但爲什麼希望編譯器能夠以最小的努力完成。在分析字節碼或測量性能差異之前,我會簡單地自行優化它。 – MrSmith42

回答

7

我認爲這個習慣用法會導致雙打,然後在每次通過時重新分配,但不會導致額外的垃圾,從而減少我造成的GC數量。還是虛擬機比這更聰明?

Primitive local variables live on the stack,不是堆,所以根本不需要GC'd。只要函數返回,它們就會實際上消失 - 因爲它會清除堆棧幀。

這就是說,是的,雙打被重新分配,因爲這是你寫的代碼說要做的。如果要提高此特定方法的速度,則當longitudelatitude設置爲時,計算longRadslatRads。做到這一點的正確方法是總是委託將這些字段設置爲setter方法。例如:

public void setLongitude(double longitude) { 
    this.longitude = longitude; 
    this.longRags = longitude * (Math.PI/180); 
} 

這當然會使得設置一個較慢的操作,但這不是你詢問的優化問題。

+0

哇。我花了很多年製作這個問題,答案很簡單。這次真是萬分感謝。非常有用的知道。 – Simon

+0

同意在setter中做這件事,如果時間允許的話,我可以這樣做(這是一個端口),但這種方法只有在緯度和長度發生變化時纔會被調用,所以我不會減少calcs。爲了清楚起見,我沒有表明,經濟長期是該方法的論點。 – Simon