這個問題是從 TeX - LaTeX Stack Exchange遷移而來的,因為它可以在 Stack Overflow 上得到回答。 昨天遷移 。
人們常說應該在本地重新宣告(某些)Lua 函式,因為這樣可以減少開銷。但這背后的確切規則/原則是什么?我怎么知道這應該針對哪些功能完成,哪些功能是多余的?還是應該為每個功能完成,甚至是你自己的?
不幸的是,我無法從 Lua 手冊中弄清楚。
uj5u.com熱心網友回復:
其原理是,每次撰寫table.insertexample 時,Lua 解釋器都會"insert"在表中查找名為table. 實際上,這意味著_ENV.table.insert-_ENV是 Lua 5.2 中“全域變數”所在的位置。Lua 5.1 有類似的東西,但不叫_ENV. 解釋器在其中查找字串"table",_ENV然后"insert"在該表中查找字串。table.insert在函式實際被呼叫之前,每次呼叫時都會進行兩次表查找。
但是如果你把它放在一個區域變數中,那么解釋器直接從區域變數中獲取函式,這樣更快。它仍然需要查找它,以填充區域變數。
如果您只在區域變數的范圍內呼叫該函式一次,那是多余的,但這種情況很少見。對于已經宣告為local. 它還使代碼更難閱讀,因此通常您不會這樣做,除非它確實很重要(在運行很多次的代碼中)。
uj5u.com熱心網友回復:
我最喜歡的 Lua 加速工具是將表中所有可用的東西放在一個名為: __index 的元表中。
一個常見的例子是資料型別:string
它在他的 __index 元表中具有所有字串函式作為方法。
因此,您可以直接在字串上執行類似的操作...
print(('istaqsinaayok'):upper():reverse())
-- Output: KOYAANISQATSI
上面的邏輯...
在字串中查找方法直接失敗,因此將為該方法查找 __index 元方法。
我喜歡為資料型別編號實作相同的行為......
-- do debug.setmetatable() only once for all further defined/used numbers
math.pi = debug.setmetatable(math.pi, {__index = math})
-- From now numbers are objects ;-)
-- Lets output Pi but not using Pi this time
print((180):rad()) -- Pi calcing with method rad()
-- Output: 3.1415926535898
邏輯:如果不存在,則查找 __index
僅落后一步:本地
...恕我直言。
另一個例子,適用于這種方法......
-- koysenv.lua
_G = setmetatable(_G,
{ -- Metamethods
__index = {}, -- Table constructor
__name = 'Global Environment'
})
-- Reference whats in _G into __index
for key, value in pairs(_G) do
getmetatable(_G)['__index'][key] = value
end
-- Remove all whats in __index now from _G
for key, value in pairs(getmetatable(_G)['__index']) do
_G[key] = nil
end
return _G
當作為最后一個要求啟動時,它會將 _G 中的所有內容移動到新創建的元表方法 __index 中。
之后 _G 看起來完全是空的;-P
...但是環境正在運行,就像什么都沒發生一樣。
uj5u.com熱心網友回復:
添加到@user253751 已經說過的內容:
代碼質量
Lua 是一種非常靈活的語言。其他語言要求您匯入您使用的標準庫的部分;盧亞沒有。Lua 通常提供一個不受污染的全域環境。如果您使用環境_ENV(setfenv/ getfenvon Lua 5.1 / LuaJIT),您仍希望能夠訪問 Lua 庫。為此,您可以在更改環境之前對它們進行本地化;然后,您可以為您的模塊/API 表/類/任何東西使用您的“干凈”環境。這里的另一個選擇是使用元表;元表鏈可能很快就會變得多毛,并且可能會損害性能,因為每次都需要失敗的表查找來觸發索引元方法。local因此,對其他全域變數進行化可以被視為匯入它們的一種方式;舉一個最小和粗略的例子:
local print = print -- localize ("import") everything we need first
_ENV = {} -- set environment to clean table for module
function hello() -- this writes to _ENV instead of _G
print("Hello World!")
end
hello() -- inside the environment, all variables set here are accessible
return _ENV -- "export" the API table
表現
非常小的挑剔:區域變數并不總是更快。在非常極端的情況下(即很多 upvalues),索引表(如果它是環境、字串 metatable 等則不需要 upvalue)實際上可能更快。
我想,許多優化編譯器(例如 LuaJIT)的優化都需要本地化變數才能適用;否則 Lua 撰寫的代碼很少。全域likeprint可能會在深度代碼路徑中的某處被覆寫——因此每次都必須重復索引操作;另一方面,對于本地人來說,解釋器將對其范圍有更多保證。因此,它能夠檢測僅寫入一次的常量,例如在初始化時;對于全域而言,幾乎沒有代碼分析是可能的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/466543.html
