2010-08-24 43 views
6

我一直在使用Java進行Android編程。由於性能對於我正在處理的內容非常重要,所以我最終只會發送垃圾郵件全局變量。我想現在每個人都會衝過來,告訴我這是有史以來最糟糕的風格,但讓我們保持簡單。對於Android來說,局部變量意味着垃圾收集和垃圾收集是殺死性能的東西。保留一個全局變量或在c中重新創建一個局部變量?

最近我已經開始使用NDK。現在我感受到實際採取所有局部變量並將其改變爲全局變量的衝動。我想知道,如果這在c代碼中有任何意義。顯然這不是一種好風格,但如果速度需要,我會很樂意犧牲風格。

我已經瀏覽了一些關於本地和全局的舊主題,但是我一直無法找到關於速度的任何信息。所以我的問題是,如果我經常調用一個函數,那麼與函數完成後創建局部變量和死亡的速度有關嗎?或者根本不重要,我可以高興地繼續使用局部變量。

我會自己測試一下,但由於某種原因,我的應用程序的性能像雲霄飛車一樣上下起伏,我懷疑我能夠真正瞭解數據。我希望有人可以幫我把我的整個代碼改寫爲空:)

+1

你爲什麼認爲「局部變量意味着垃圾收集」? – 2010-08-24 22:16:41

+0

由於局部變量在超出範圍時被垃圾收集。 – Crashworks 2010-08-24 22:26:34

+0

而全局變量是a)當設置爲NULL時收集的垃圾;或b)保存在內存中,因此不使用時不必要地增加內存壓力,如果不設置爲NULL。 – 2010-08-24 22:29:06

回答

8

在C中,性能的差異取決於硬件。在RISC處理器上加載全局更多的指令(​​因爲你必須在單獨的指令中加載地址的兩半,而不是堆棧指針),然後你需要與緩存問題抗爭。大多數情況下,您可以指望您的本地變量位於緩存中。使用全局變量會使緩存溢出一點,某些函數可能會受到非常不利的影響。

如果在運行應用程序時性能變化很大,那麼很可能您關於局部變量對性能影響的斷言並不重要。

在C中創建局部變量的「成本」爲零;它只是衝擊一個寄存器(堆棧指針)爲本地騰出空間。然後通過任何適當的方法初始化該變量。你應該能夠知道這是否昂貴或不隨意檢查。當函數退出時,無論您有多少局部變量,堆棧指針都會返回到其先前的值。

如果您的「局部變量」的定義是堆分配的對象,但是,您將遭受內存分配的成本。在我看來,內存分配非常緩慢,所以無論你如何擺脫malloc/free(以及Java中的'new'),你都會變得越好。 (我做遊戲,我們傾向於使用dlmalloc但即使是對於經常使用過於緩慢;每次通話400ns的快速加起來)

+0

謝謝你的快速回復!我想我還有很多東西要學,但是我很高興我可以繼續在c中使用局部變量,這在java中是一種痛苦。你的評論,我想我選了錯誤的話,但我注意到,如果我每秒調用一次函數20次,並且在我創建的函數中(例如一個本地int),這個函數完成後就會被垃圾回收,花費很多時間 這就是爲什麼我結束了很多全局變量 – Pandoro 2010-08-24 22:31:24

+0

即使在Java中,本地整型或其他原始數據類型也不應該要求任何花哨的垃圾回收 – 2010-08-24 22:36:43

11

對於Android,局部變量是指垃圾收集...

這是一個不正確的陳述。局部變量分配在堆棧上 - 不是在堆上動態分配的。檢查出this article分配的內容在Java中的分配情況

通常,在堆棧上分配的項不需要垃圾收集/釋放並立即「死」在執行離開它的當前範圍之後。堆分配/取消分配是明顯比堆分配和垃圾回收速度快

儘量避免出於樣式和性能原因的全局變量。堆棧分配的本地變量將執行得更快。

+0

好知道!因爲我總是嘗試過所有全局vs所有局部變量我在全局方法中獲得了更好的性能,主要是因爲我使用了很多對象和數組,但是如果我找到了正確的方法,我可以保留所有原始數據類型,因爲他們贏了無論如何,你不會去堆嗎? – Pandoro 2010-08-24 22:39:58

+0

+1很遺憾,很多Java程序員不知道堆棧和堆分配之間的區別。但我必須承認,直到我學會了C我也沒有打擾:-)。 – helpermethod 2010-08-24 22:41:18

+0

@Pandoro請參閱http://cslibrary.stanford.edu/102/PointersAndMemory.pdf。這真是讓我大開眼界。 – helpermethod 2010-08-24 22:42:55

2

在大多數Android手機中發現的基於MIPS和ARM的CPU上,沒有任何理由將本地變量移到全局空間以「提高性能」。本地存儲在堆棧上,堆棧分配是單個操作;而且整個堆棧在調用ret時立即清除。將它們移動到全球空間只會讓你的邏輯陷入一個無法解讀的混亂無序狀態。

創建對象時需要考慮的一個地方是當你在堆上分配它們時(例如使用malloc())。這正是C比「垃圾收集語言」更「高性能」的地方,因爲您可以準確地看到並控制這些malloc何時發生以及何時被釋放。實際上C malloc()比Java new更快;相反,因爲每個分配對您都是透明和明確的,您可以進行必要的工作以確保這種緩慢的操作儘可能少發生。

+0

同意。實際上,'malloc'通常比'new'慢,GC掃描速度通常比相應的'free'調用速度快。但是專家C編碼器習慣於對內存分配進行足夠小心,以彌補差異(或者編寫自己的專用內存處理例程,這些例程對於其使用情況甚至更快)。 – 2010-08-25 15:55:01

0

順便說一下,在C函數中聲明一個變量static將會給你一個全局的行爲,而不會拋出全局名稱空間。

但如前所述,聲明堆棧上的自動變量需要0時間並且訪問這些變量也非常快,所以沒有太多理由避免函數局部變量。

如果你真的需要這種極端的優化級別,你應該考慮將所有常用函數內聯以避免通話開銷。