lua使用優化建議

1.使用局部變量local

這是最基礎也是最有用的策略,雖然使用全局變量並不能完全避免,但還是應該儘量避免,取而代之使用局部變量即local。這裏的局部變量也包括函數function,因爲在Lua裏函數也是一個變量。局部變量的存取會更快,而且在生命週期之外就會釋放掉。

使用全局變量

CCX = display.contentCenterX  --global variable
for i = 1,100 do
   local image = display.newImage( "myImage" )
   image.x = CCX
end

使用局部變量

local CCX = display.contentCenterX  --local variable
for i = 1,100 do
   local image = display.newImage( "myImage" )
   image.x = CCX
end

這個原則也適用於Lua的核心庫,比如math庫。對於這類函數也應該使用局部變量。

非局部變量

local function foo( x )
   for i = 1,100 do
      x = x + math.sin(i)
   end
   return x
end

使用局部變量

local sin = math.sin  --local reference to math.sin
local function foo(x)
   for i = 1,100 do
      x = x + sin(i)
   end
   return x
end

最後,記住儘量用局部變量的方式來使用函數。當然,這樣需要注意函數的作用域的問題。如果你對Lua的作用域還不夠清楚,請看Understanding “SCOPE” for beginning programmers


2.避免將函數體定義作爲其他函數的參數來使用

如果函數的參數是函數時,應將參數函數作爲局部變量傳進參數,而不要直接寫函數定義,請看下面兩個例子:

直接在參數表裏定義函數

local func1 = function(a,b,func)
   return func(a+b)
end
for i = 1,100 do
   local x = func1( 1, 2, function(a) return a*2 end )
   print( x )
end

使用局部變量傳參 -- local 標記的函數或變量只能用在當前作用域,如果函數參數是傳遞給其他類或文件的,請不要貪圖這丁點效率

local func1 = function( a, b, func )
   return func( a+b )
end
local func2 = function( c )
   return c*2
end
for i = 1,100 do
   local x = func1( 1, 2, func2 )
   print( x )
end

3.避免使用table.insert()

下面來看看4個實現表插入的方法。在4個方法之中table.insert()在效率上不如其他方法,是應該避免使用的。

使用table.insert

local a = {}
local table_insert = table.insert
for i = 1,100 do
   table_insert( a, i )
end

使用循環的計數

local a = {}
for i = 1,100 do
   a[i] = i
end

使用table的size

local a = {}
for i = 1,100 do
   a[#a+1] = i
end

使用計數器

local a = {}
local index = 1
for i = 1,100 do
   a[index] = i
   index = index+1
end

4.減少使用 unpack()函數

Lua的unpack()函數不是一個效率很高的函數。你完全可以寫一個循環來代替它的作用。

使用unpack()

local a = { 100, 200, 300, 400 }
for i = 1,100 do
   print( unpack(a) )
end

代替方法

local a = { 100, 200, 300, 400 }
for i = 1,100 do
   print( a[1],a[2],a[3],a[4] )
end

5.緩存table的元素

緩存table的元素,特別是在循環內使用會提高效率。

未緩存

for i = 1,100 do
   for n = 1,100 do
      a[n].x = a[n].x + 1
      print( a[n].x )
   end
end

緩存 -- 只適合引用類型,而對於值類型只適合讀取數據不能存儲新值

for i = 1,100 do
   for n = 1,100 do
      local y = a[n]
      y.x = y.x + 1
      print( y.x )
   end
end

6.避免使用ipairs()

當遍歷table時,使用Lua的ipairs()的效率並不高。

使用ipairs() -- 對於非順序數字索引的只能用pairs()

local t1 = {}
local t2 = {}
local t3 = {}
local t4 = {}
local a = { t1, t2, t3, t4 }
for i,v in ipairs( a ) do
   print( i,v )
end

代替方法

local t1 = {}
local t2 = {}
local t3 = {}
local t4 = {}
local a = { t1, t2, t3, t4 }
for i = 1,#a do
   print( a[i] )
end

7.數學方法的效率比較

應該使用更快的數學方法。

避免對正數使用math.fmod()

--math.fmod method (discouraged)
local fmod = math.fmod
for i = 1,100 do
   if ( fmod( i,30 ) < 1 ) then
      local x = 1
   end
end
--modulus operator method (recommended)
for i = 1,100 do
   if ( ( i%30 ) < 1 ) then
      local x = 1
   end
end

乘法比除法快

x * 0.5 ; x * 0.125  --recommended
x/2 ; x/8            --discouraged

乘法比乘冪快

x * x * x  --recommended
x^3        --discouraged

8.保存Texture內存

Texture內存一般只有在出現警告時纔會去關注,但那時就很難去補救了。

  1. 當texture不需要的時候記得釋放掉。
  2. 如果你有一個525×600的背景圖片,你可以改成448×512的。因爲OpenGL對圖片內存遵循2的倍數原則,即每次使用內存都是以2的倍數爲長度的。所以525×600的圖片將會消耗1024*1024的內存(即1024×1024 (pixels) × 4 (bytes) = 4,194,304 bytes = 4 MB),而448×512只會消耗1/4的內存。在圖片清晰度容忍的情況下儘量縮小到下一個2倍量級內。
  3. 儘可能的重複利用素材。對於圖片相同而顏色不同的可以使用setFillColor函數。例如你有紅蘋果和青蘋果,那麼你可以創建一個灰度的圖片然後分別添加紅色和綠色。
  4. 如果你使用image sheet,那麼一定要使用類似TexturePacker的軟件,不僅能提高開發效率也能優化圖片大小。

9.預先創建物理對象

如果你要在場景中使用一定數量的物理對象,那麼預先創建所有的對象會在使用時提高效率。那些暫時用不到的對象可以設置爲未激活的狀態然後放到屏幕的外面或者放到一個不可見的group裏。當需要時設置對於的位置並激活即可。 實時創建物理對象並不是不可以,但一次性創建10-20個對象必然會造成性能問題,而導致頓卡延時等。 當然,也要考慮到內存的問題,如果一開始就創建幾百個物體,那麼對於內存的消耗就使得性能提高有點得不償失了。


10.音頻使用策略

有些音效是整個app都會用到的,這樣的音效需要一開始就載入到內存中。對於音質並沒有特別高的要求的音樂和音效需要考慮是否需要壓縮,比如使用11khz來減小音頻文件的大小,一般用戶也聽不出太大的區別,而這樣減少的內存可是相當可觀的。而且要使用簡單的適合多平臺的音頻格式,比如WAV格式。 如果需要的話,音效可以如下組織成一個table,這樣便於在使用時引用或者在不需要的時候釋放掉。

--load these sounds during NON-time-critical code
local soundTable = {
   mySound1 = audio.loadSound( "a.wav" ),
   mySound2 = audio.loadSound( "b.wav" ),
   mySound3 = audio.loadSound( "c.wav" ),
   mySound4 = audio.loadSound( "d.wav" ),
   mySound5 = audio.loadSound( "e.wav" ),
   mySound6 = audio.loadSound( "f.wav" ),
   mySound7 = audio.loadSound( "g.wav" ),
   mySound8 = audio.loadSound( "h.wav" ),
}

播放一個音效就非常簡單:

local mySound = audio.play( soundTable["mySound1"] )

永遠不要忘記,當音效不需要的時候就要釋放掉:

local ST = soundTable
for s,v in pairs(ST) do
   audio.dispose( ST[s] ) ; ST[s] = nil
end



另外,引用百度知道上@wydwuf的話:

用lua之類的腳本語言編程,本來就不用考慮太多所謂效率,要效率用C去。

尤其是在lua 裏,local的最本質作用就是我說的 "數據/接口隱藏和防止全局名稱衝突"。

你去看看 lua 的語言標準,哪一句告訴你要因爲效率而使用 local? 

用不用 local 只和你具體的任務有關,和效率有什麼關係?



原文:

lua使用優化建議


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章