欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品

主頁 > 知識庫 > Lua性能優化技巧(五):削減、重用和回收

Lua性能優化技巧(五):削減、重用和回收

熱門標簽:漳州智云呼電話機器人 個人怎么在地圖標注需要的店鋪 冀州市地圖標注 怎么去除地圖標注 新岸線智能電銷機器人 武漢外呼防封系統多少錢 清朝地圖標注哈爾濱 地圖標注大廈 百度地圖標注早餐區域

當處理Lua資源時,我們也應該遵循提倡用于地球資源的3R原則——Reduce, Reuse and Recycle,即削減、重用和回收。

削減是最簡單的方式。有很多方法可以避免使用新的對象,例如,如果你的程序使用了太多的表,可以考慮改變數據的表述形式。一個最簡單的例子,假設你的程序需要操作折線,最自然的表述形式是:

復制代碼 代碼如下:

polyline =
{
    { x = 10.3, y = 98.5 },
    { x = 10.3, y = 18.3 },
    { x = 15.0, y = 98.5 },
    --...
}

盡管很自然,這種表述形式對于大規模的折線來說卻不夠經濟,因為它的每個點都需要用一個表來描述。第一種替代方式是使用數組來記錄,可以省點內存:

復制代碼 代碼如下:

polyline =
{
     { 10.3, 98.5 },
     { 10.3, 18.3 },
     { 15.0, 98.5 },
     --...
}

對于一個有一百萬個點的折線來說,這個修改可以把內存占用從95KB降低到65KB。當然,你需要在可讀性上付出代價:p[i].x比p[i][1]更易懂。

另一個更經濟的做法是使用一個數組存儲所有x坐標,另一個存儲所有y坐標:

復制代碼 代碼如下:

polyline =
{
    x = { 10.3, 10.3, 15.0, ...},
    y = { 98.5, 18.3, 98.5, ...}
}

原有的
復制代碼 代碼如下:

p[i].x

現在變成了
復制代碼 代碼如下:

p.x[i]

使用這種表述形式,一百萬個點的折線的內存占用降低到了24KB。

循環是尋找降低垃圾回收次數的機會的好地方。例如,如果在循環里創建一個不會改變的表,你可以把它挪到循環外面,甚至移到函數外作為上值。試對比:

復制代碼 代碼如下:

function foo (...)
     for i = 1, n do
          local t = {1, 2, 3, "hi"}
          -- 做一些不會改變t表的事情
          --...
     end
end


復制代碼 代碼如下:

local t = {1, 2, 3, "hi"} -- 創建t,一勞永逸
function foo (...)
    for i = 1, n do
        --做一些不會改變t表的事情
        --...
    end
end

相同的技巧亦可用于閉包,只要你不把它們移到需要它們的作用域之外。例如下面的函數:

復制代碼 代碼如下:

function changenumbers (limit, delta)
    for line in io.lines() do
        line = string.gsub(line, "%d+", function (num)
            num = tonumber(num)
            if num >= limit then return tostring(num + delta) end
            -- 否則不返回任何值,保持原有數值
        end)
        io.write(line, "\n")
    end
end

我們可以通過將內部的函數移到循環外面來避免為每次迭代創建新的閉包:

復制代碼 代碼如下:

function changenumbers (limit, delta)
    local function aux (num)
        num = tonumber(num)
        if num >= limit then return tostring(num + delta) end
    end
    for line in io.lines() do
        line = string.gsub(line, "%d+", aux)
        io.write(line, "\n")
    end
end

但是,我們不能把aux移到changenumbers函數之外,因為aux需要訪問limit和delta。

對于多種字符串處理,我們可以通過使用現有字符串的索引來減少對創建新字符串的需要。例如,string.find函數返回它找到指定模式的位置索引,而不是匹配到的字符串。通過返回索引,它避免了在成功匹配時創建新的字符串。當有必要時,程序員可以通過調用string.sub來獲取匹配的子串[1]。

當我們無法避免使用新的對象時,我們依然可以通過重用來避免創建新的對象。對于字符串來說,重用沒什么必要,因為Lua已經為我們做了這樣的工作:它總是將所有用到的字符串內部化,并在所有可能的時候重用。然而對于表來說,重用可能就非常有效。舉一個普遍的例子,讓我們回到在循環里創建表的情況。這一次,表里的內容不再是不變的。通常我們可以在所有迭代中重用這個表,只需要簡單地改變它的內容??紤]如下的代碼段:

復制代碼 代碼如下:

local t = {}
for i = 1970, 2000 do
    t[i] = os.time({year = i, month = 6, day = 14})
end

下面的代碼是等同的,但是重用了這張表:
復制代碼 代碼如下:

local t = {}
local aux = {year = nil, month = 6, day = 14}
for i = 1970, 2000 do
    aux.year = i
    t[i] = os.time(aux)
end

實現重用的一個尤其有效的方式是緩存化[2]。基本思想非常簡單,將指定輸入對應的計算結果存儲下來,當下一次再次接受相同的輸入時,程序只需簡單地重用上次的計算結果。

LPeg,Lua的一個新的模式匹配庫,就使用了一個有趣的緩存化處理。LPeg將每個模式字符串編譯為一個內部的用于匹配字符串的小程序,比起匹配本身而言,這個編譯過程開銷很大,因此LPeg將編譯結果緩存化以便重用。只需一個簡單的表,以模式字符串為鍵、編譯后的小程序為值進行記錄。

使用緩存化時常見的一個問題是,存儲計算結果所帶來的內存開銷大過重用帶來的性能提升。為了解決這個問題,我們可以在Lua里使用一個弱表來記錄計算結果,因此沒有使用到的結果最終將會被回收。

在Lua中,利用高階函數,我們可以定義一個通用的緩存化函數:

復制代碼 代碼如下:

function memoize (f)
    local mem = {} -- 緩存化表
    setmetatable(mem, {__mode = "kv"}) -- 設為弱表
    return function (x) -- ‘f'緩存化后的新版本
        local r = mem[x]
        if r == nil then --沒有之前記錄的結果?
            r = f(x) --調用原函數
            mem[x] = r --儲存結果以備重用
        end
        return r
    end
end

對于任何函數f,memoize(f)返回與f相同的返回值,但是會將之緩存化。例如,我們可以重新定義loadstring為一個緩存化的版本:

loadstring = memoize(loadstring)
新函數的使用方式與老的完全相同,但是如果在加載時有很多重復的字符串,性能會得到大幅提升。

如果你的程序創建和刪除太多的協程,循環利用將可能提高它的性能?,F有的協程API沒有直接提供重用協程的支持,但是我們可以設法繞過這一限制。對于如下協程:

復制代碼 代碼如下:

co = coroutine.create(function (f)
    while f do
        f = coroutine.yield(f())
    end
end)

這個協程接受一項工作(運行一個函數),執行之,并且在完成時等待下一項工作。

Lua中的多數回收都是通過垃圾回收器自動完成的。Lua使用漸進式垃圾回收器,意味著垃圾回收工作會被分成很多小步,(漸進地)在程序的允許過程中執行。漸進的節奏與內存分配的速度成比例,每當分配一定量的內存,就會按比例地回收相應的內存;程序消耗內存越快,垃圾回收器嘗試回收內存也就越快。

如果我們在編寫程序時遵循削減和重用的原則,通常垃圾回收器不會有太多的事情要做。但是有時我們無法避免制造大量的垃圾,垃圾回收器的工作也會變得非常繁重。Lua中的垃圾回收器被調節為適合平均水平的程序,因此它在多數程序中工作良好。但是,在特定的時候我們可以通過調整垃圾回收器來獲取更好的性能。通過在Lua中調用函數collectgarbage,或者在C中調用lua_gc,來控制垃圾回收器。它們的功能相同,只不過有不同的接口。在本例中我將使用Lua接口,但是這種操作通常在C中進行更好。

collectgarbage函數提供若干種功能:它可以停止或者啟動垃圾回收器、強制進行一次完整的垃圾回收、獲取Lua占用的總內存,或者修改影響垃圾回收器工作節奏的兩個參數。它們在調整高內存消耗的程序時各有用途。

“永遠”停止垃圾回收器可能對于某些批處理程序很有用。這些程序創建若干數據結構,根據它們生產出一些輸出值,然后退出(例如編譯器)。對于這樣的程序,試圖回收垃圾將會是浪費時間,因為垃圾量很少,而且內存會在程序執行完畢后完整釋放。

對于非批處理程序,停止垃圾回收器則不是個好主意。但是,這些程序可以在某些對時間極度敏感的時期暫停垃圾回收器,以提高時間性能。如果有需要的話,這些程序可以獲取垃圾回收器的完全控制,使其始終處于停止狀態,僅在特定的時候顯式地進行一次強制的步進或者完整的垃圾回收。例如,很多事件驅動的平臺都提供一個選項,可以設置空閑函數,在沒有消息需要處理時調用。這正是調用垃圾回收的絕好時機(在Lua 5.1中,每當你在垃圾回收器停止的狀態下進行強制回收,它都會恢復運轉,因此,如果要保持垃圾回收器處于停止狀態,必須在強制回收后立刻調用collectgarbage("stop"))。

最后,你可能希望實施調整回收器的參數。垃圾回收器有兩個參數用于控制它的節奏:第一個,稱為暫停時間,控制回收器在完成一次回收之后和開始下次回收之前要等待多久;第二個參數,稱為步進系數,控制回收器每個步進回收多少內容。粗略地來說,暫停時間越小、步進系數越大,垃圾回收越快。這些參數對于程序的總體性能的影響難以預測,更快的垃圾回收器顯然會浪費更多的CPU周期,但是它會降低程序的內存消耗總量,并可能因此減少分頁。只有謹慎地測試才能給你最佳的參數值。

[1] 如果標準庫提供一個用于對比兩個子串的函數可能會是一個好主意,這樣我們無需將子串解出(會創建新的字符串)即可檢查字符串中的特定值。

[2] 緩存化,原文memoize

您可能感興趣的文章:
  • Lua性能優化技巧(一):前言
  • Lua性能優化技巧(二):基本事實
  • Lua性能優化技巧(三):關于表
  • Lua性能優化技巧(四):關于字符串
  • Lua性能優化技巧(六):最后的提示

標簽:德宏 天門 天門 金昌 濰坊 臺灣 儋州 宣城

巨人網絡通訊聲明:本文標題《Lua性能優化技巧(五):削減、重用和回收》,本文關鍵詞  Lua,性能,優化,技巧,五,削減,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Lua性能優化技巧(五):削減、重用和回收》相關的同類信息!
  • 本頁收集關于Lua性能優化技巧(五):削減、重用和回收的相關信息資訊供網民參考!
  • 推薦文章
    欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品
  • <rt id="w000q"><acronym id="w000q"></acronym></rt>
  • <abbr id="w000q"></abbr>
    <rt id="w000q"></rt>
    久久久久国产成人精品亚洲午夜| 国产乱码精品一区二区三| 成人av资源下载| 国产一二三四视频| 久久亚洲综合色一区二区三区| 日韩精品电影一区亚洲| 精品人妻伦一二三区久| 欧美日韩国产综合一区二区 | 真实乱偷全部视频| 在线免费观看不卡av| 亚洲激情图片一区| 99热这里只有精品2| 欧美在线视频你懂得| 一区二区三区四区国产精品| 日本人dh亚洲人ⅹxx| 欧美日本一区二区三区四区| 亚洲成人精品一区二区| 亚洲视频在线播放免费| 欧美不卡一区二区| 韩国女主播一区二区三区| 91资源在线播放| 国产精品嫩草99a| 不卡欧美aaaaa| 欧美在线观看视频一区二区三区| 亚洲精品视频在线看| 日本wwwxx| 欧美一级久久久| 精品一区二区三区视频在线观看| 国产午夜福利一区| 国产精品福利一区| 91精品人妻一区二区三区四区| 欧美久久一二区| 日韩电影在线一区二区| 天天操天天干天天操天天干| 国产精品成人午夜| 久久久久久久久久久影视| 3751色影院一区二区三区| 六月丁香婷婷色狠狠久久| 中文天堂资源在线| 国产精品二三区| 精品国产免费久久久久久婷婷| 69av一区二区三区| 精品在线你懂的| 色哟哟精品一区| 亚洲sss视频在线视频| 久久精品国产亚洲AV熟女| 久久影视一区二区| 99精品一区二区三区| 欧美一级片在线看| 国产高清在线观看免费不卡| 在线观看成人小视频| 日韩国产欧美在线播放| 看黄色录像一级片| 午夜精品久久久久久久99樱桃| 日本二区在线观看| 亚洲黄色小说网站| www.av欧美| 亚洲欧洲av另类| 国产精品一区二区入口九绯色| 国产免费观看久久| 少妇精品无码一区二区三区| 国产日本欧美一区二区| 在线播放av网址| 国产无一区二区| 国产人妻精品午夜福利免费| 精品国产乱码久久久久久图片 | 91蜜桃视频在线| 精品国产一区二区三区久久影院| 成人丝袜18视频在线观看| 7799精品视频| 成人免费av资源| 欧美va亚洲va在线观看蝴蝶网| 成人国产精品免费观看动漫| 日韩一区二区麻豆国产| 不卡的av中国片| 精品盗摄一区二区三区| 成人在线短视频| 欧美国产日本韩| av网页在线观看| 国产精品国产a| 免费看污片的网站| 亚洲成人自拍偷拍| 高h视频免费观看| 国精产品一区一区三区mba桃花 | 亚洲制服丝袜在线播放| 成人欧美一区二区三区黑人麻豆| 一级特级黄色片| 一区二区久久久久久| 国产黄a三级三级| 麻豆国产精品一区二区三区| 欧美优质美女网站| 成人亚洲一区二区一| www一区二区| 亚洲观看黄色网| 一区二区欧美在线观看| 久久国产精品国语对白| 久久国产三级精品| 6080午夜不卡| 亚洲少妇一区二区三区| 亚洲欧洲综合另类| 91香蕉一区二区三区在线观看| 美女视频一区二区| 欧美一卡2卡三卡4卡5免费| 少妇丰满尤物大尺度写真| 亚洲欧洲另类国产综合| 国产探花在线视频| 国产一区在线观看视频| 欧美成人r级一区二区三区| 色综合久久五月| 午夜精品免费在线| 欧美高清你懂得| 91人人澡人人爽| 夜夜嗨av一区二区三区中文字幕| 一本色道久久综合亚洲精品按摩| 懂色av一区二区三区蜜臀 | 女人被狂躁c到高潮| 亚洲 欧美综合在线网络| 欧美午夜一区二区三区| 99国产精品久久久| 亚洲免费观看高清完整版在线观看| 999精品视频在线观看播放 | 久久综合色婷婷| 亚洲自拍偷拍图| 精品一区二区三区av| 精品国产免费一区二区三区香蕉| 国产男男chinese网站| 日本视频免费一区| 日韩女优av电影| 老熟妇一区二区| 久久99精品久久久| 久久久噜噜噜久久中文字幕色伊伊| 国产成人av一区二区三区不卡| 蜜桃视频一区二区三区在线观看 | 无码国产精品一区二区高潮| 洋洋成人永久网站入口| 欧美日韩高清一区二区不卡| 色悠悠在线视频| 琪琪一区二区三区| 久久综合成人精品亚洲另类欧美| 伊人网伊人影院| 国产乱对白刺激视频不卡| 中文字幕欧美日韩一区| 懂色av懂色av粉嫩av| 91丨九色丨蝌蚪丨老版| 亚洲自拍欧美精品| 制服视频三区第一页精品| 国产中文字幕一区二区| 精品亚洲aⅴ乱码一区二区三区| 久久久影院官网| 国产又粗又长又黄的视频| 高清shemale亚洲人妖| 亚洲丝袜美腿综合| 欧美欧美欧美欧美首页| 成人h动漫精品一区| 国产一区二区在线看| 中文字幕中文在线不卡住| 欧美少妇xxx| 玖玖爱在线观看| 国产成a人亚洲精品| 亚洲欧美另类综合偷拍| 在线成人av影院| 久久亚洲AV无码专区成人国产| 国产精品羞羞答答xxdd| 亚洲欧美日韩国产成人精品影院| 69久久夜色精品国产69蝌蚪网| xxxx日本黄色| 成人免费看黄yyy456| 亚洲.国产.中文慕字在线| 久久久久久久综合| 在线视频一区二区三区| 久久一区二区电影| 国产成人h网站| 亚洲午夜国产一区99re久久| 欧美大胆一级视频| 91aaa在线观看| 玖草视频在线观看| 成人晚上爱看视频| 日本欧美一区二区三区| 国产精品久久精品日日| 777午夜精品免费视频| 美女福利视频网| 熟妇高潮一区二区| 国产风韵犹存在线视精品| 亚洲与欧洲av电影| 久久精品亚洲精品国产欧美| 欧美午夜免费电影| 欧美美女性生活视频| 国产 xxxx| 波多野结衣在线aⅴ中文字幕不卡| 日韩av电影免费观看高清完整版在线观看| 欧美极品aⅴ影院| 91精品国产福利| 亚洲色婷婷一区二区三区| 国产夫妻性爱视频| 97se亚洲国产综合自在线观| 美女网站色91| 香蕉成人啪国产精品视频综合网 | 亚洲国产精品尤物yw在线观看| 久久先锋影音av鲁色资源网| 欧美三级视频在线播放|