Lua | 每日一練 (3)

💢歡迎來到張胤塵的技術站
💥技術如江河,匯聚眾志成。代碼似星辰,照亮行征程。開源精神長,傳承永不忘。攜手共前行,未來更輝煌💥

文章目錄

  • Lua | 每日一練 (3)
    • 題目
    • 參考答案
      • 減少查找次數
      • 預分配表空間
        • 數組部分(連續整數索引)
        • 哈希部分(非整數索引)
      • 減少嵌套深度
      • 避免表中存在非連續索引
        • 使用獨立的表
        • 避免稀疏數組
        • 清理表中的空隙,優化表的結構
      • 常使用元表和元方法優化
      • 減少垃圾回收的開銷
      • 減少全局變量的使用

Lua | 每日一練 (3)

題目

lua 中的 table 性能優化有哪些技巧?

參考答案

tablelua 的一種數據結構用來創建不同的數據類型,例如:數組、字典。table 的能力是非常強大的,但是如果在使用過程中不注意優化細節,可能會性能產生一定的影響。

下面針對使用 table 過程中的常見優化手段進行總結。

減少查找次數

lua 中,表查找(尤其是多重嵌套表的查找)可能會因為頻繁的鍵訪問而變得相對低效。例如:

local myTable = {nested = {value = 10}
}-- 低效:每次循環都進行表查找
for i = 1, 1000000 dolocal v = myTable.nested.value-- 使用 v 做一些操作
end

如果某個表的值在循環或其他頻繁執行的代碼塊中被多次訪問,可以將其緩存到局部變量中。這樣可以避免每次訪問時都進行表查找。

修改后的代碼如下所示:

local myTable = {nested = {value = 10}
}-- 高效:將值緩存到局部變量
local cachedValue = myTable.nested.value
for i = 1, 1000000 dolocal v = cachedValue-- 使用 v 做一些操作
end

另外如果需要頻繁的訪問某個表,可以鍵表本身緩存到局部變量中,這樣可以減少每次訪問時的查找路徑,例如:

local myTable = {nested = {value = 10}
}-- 低效:每次訪問都從根表開始查找
for i = 1, 1000000 dolocal v = myTable.nested.value-- 使用 v 做一些操作
end

修改后的代碼如下所示:

local myTable = {nested = {value = 10}
}-- 高效:緩存嵌套表的引用
local nestedTable = myTable.nested
for i = 1, 1000000 dolocal v = nestedTable.value-- 使用 v 做一些操作
end

預分配表空間

經常在循環中進行表分配,頻繁的表分配會增加垃圾回收的負擔,從而影響性能。

因為 lua 中的表分為數組部分和哈希部分,所以預分配表也分為兩部分:預分配數組部分、預分配哈希部分。

數組部分(連續整數索引)

如果表主要用于存儲連續的整數索引數據(類似數組),可以通過以下方式預分配空間:

local size = 100000  -- 預分配的大小
local t = {}
t[size] = true  -- 觸發預分配

通過將表的最后一個索引位置賦值,lua 會為表的數組部分分配足夠的空間,從而避免后續插入元素時的擴容操作。

哈希部分(非整數索引)

如果表主要用于存儲非整數索引(如字符串鍵),可以通過以下方式預分配哈希部分的空間:

local size = 100000  -- 預分配的大小
local t = {}
for i = 1, size dot["key" .. i] = true  -- 觸發哈希部分的預分配
end

減少嵌套深度

嵌套表的深度會影響查找效率。如果可能,盡量減少表的嵌套層級,或者將常用的數據提升到更淺的層級。例如:

-- 原始結構
local myTable = {level1 = {level2 = {value = 10}}
}-- 訪問優化前的表
local k = myTable.level1.level2.value-- 優化:減少嵌套層級
local myTable = {value = 10,level1 = {-- 其他數據}
}-- 訪問優化后的表
local v = myTable.value

避免表中存在非連續索引

由于表可以同時作為數組(連續索引)也可以作為哈希表(非連續索引),那么當表中同時存在連續索引和非連續索引時,可能會導致性能下降和內存浪費。

首先需要搞明白為什么存在非連續會影響性能?

  • 第一,如果表中同時存在連續索引和非連續索引,lua 會同時維護這兩部分,導致內存分配和管理變得更加復雜,增加了內存開銷。
  • 第二,對于連續索引的數組,lua 可以通過簡單的指針偏移快速訪問元素;而對于非連續索引,lua 需要進行哈希查找,這會增加訪問時間。
  • 第三,非連續索引的表會增加垃圾回收的復雜性,因為 lua 需要同時處理數組部分和哈希部分的內存回收。
使用獨立的表

如果需要存儲不同類型的數據(數組和哈希表),建議使用兩個獨立的表,而不是混合在同一個表中。例如:

-- 混合使用
local t = {1, 2, 3}
t["key"] = "value"-- 使用兩個獨立的表
local array = {1, 2, 3}
local hash = {key = "value"}
避免稀疏數組

稀疏數組(即存在大量空隙的數組)會導致表的內部結構變得復雜。如果需要使用稀疏數組,建議使用哈希表代替。例如:

-- 稀疏數組
local t = {}
t[1] = 1
t[1000000] = 1000000  -- 導致表內部結構復雜化-- 使用緊湊的哈希表結構
local t = {}
t["key1"] = 1
t["key2"] = 1000000
清理表中的空隙,優化表的結構

如果表中存在非連續索引,可以通過重新排序或清理空隙來優化表的結構。例如:

local t = {1, 2, nil, 4, 5}
local new_t = {}
for i, v in ipairs(t) doif v ~= nil thentable.insert(new_t, v)end
end
t = new_t

常使用元表和元方法優化

元表和元方法可以用于優化面向對象的代碼,減少函數調用次數,并通過元方法實現高效的常見操作,例如:

local Vector = {}function Vector:new(x, y)local obj = {}setmetatable(obj, self)self.__index = selfself.__add = function(a, b)return Vector:new(a.x + b.x, a.y + b.y)endobj.x = xobj.y = yreturn obj
endlocal v1 = Vector:new(1, 2)
local v2 = Vector:new(3, 4)
local v3 = v1 + v2print(v3.x, v3.y)

減少垃圾回收的開銷

垃圾回收的頻率會影響性能。通過重用表、避免不必要的分配以及合理調整垃圾回收參數,可以減少垃圾回收的開銷。例如:

collectgarbage("setpause", 100)  -- 設置暫停時間
collectgarbage("setstepmul", 200)  -- 設置每次回收的步長

減少全局變量的使用

lua 中,全局變量的訪問速度比局部變量慢,因為 lua 需要遍歷全局環境來進行查找。局部變量則直接存儲在棧上,訪問速度更快。另外將表定義為局部變量,可以減少全局環境的污染,提高訪問速度。例如:

-- 全局表
myGlobalTable = {value = 10}function globalTableAccess()for i = 1, 1000000 dolocal v = myGlobalTable.valueend
end-- 局部表
local myLocalTable = {value = 10}function localTableAccess()for i = 1, 1000000 dolocal v = myLocalTable.valueend
end

本文中總結的優化點可能不全面,如果大家有更好的優化點,也可以同樣可以在評論區中分享出來~~ 期待😀

🌺🌺🌺撒花!

如果本文對你有幫助,就點關注或者留個👍
如果您有任何技術問題或者需要更多其他的內容,請隨時向我提問。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/71664.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/71664.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/71664.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

二叉樹(中等題)

1、先序,中序遍歷確定二叉樹 105 方法一、 前提 ① 必須不能有重復元素② 只有先序+中序和后序+中序才能實現唯一樹 思考要點: 不要想著用for循環,遞歸一定更好解決輸入是vector,遞歸就得考慮傳入索…

服務器通過 ollama 運行deepseek r1

1、服務器環境簡介 56核 CPU64G 內存無顯卡已安裝 Ollama 2、下載模型與配置 正常可以通過 ollama pull 或 ollama run 命令直接下載,但通常會遇到連接超時、找不到網址等總理。因此,可以使用國內的模型站進行下載,在這里使用魔塔查找模型…

java項目排查線上問題1111

1.磁盤容量不足: 應用拋出的異常信息:java.io.IOException: 磁盤空間不足 1.1 指令獲取磁盤狀態:df -h 1.2 獲取目錄下文件夾大小:du -sh * 1.3 獲取目錄下文件夾大小:ls -lh 可以找到最大的文件,如日…

js中 ES6 新特性詳解

ES6(ECMAScript 2015)是 JavaScript 的一次重大更新,引入了許多新的特性,使 JavaScript 代碼更加簡潔、可讀和高效。以下是 ES6 的主要新特性及其原理 1. let 和 const 關鍵字 原理解析 1.1 作用域 var 關鍵字的作用域&#xf…

深入理解設計模式之解釋器模式

深入理解設計模式之解釋器模式 在軟件開發的復雜世界中,我們常常會遇到需要處理特定領域語言的情況。比如在開發一個計算器程序時,需要解析和計算數學表達式;在實現正則表達式功能時,要解析用戶輸入的正則表達式來匹配文本。這些場景都涉及到對特定語言的解釋和執行,而解…

巧妙實現右鍵菜單功能,提升用戶操作體驗

在動態交互式圖庫中,右鍵菜單是一項能夠顯著提升用戶操作便捷性的功能。它的設計既要響應用戶點擊位置,又需確保菜單功能與數據操作緊密結合,比如刪除圖片操作。以下將通過一段實際代碼實現,展示從思路到實現的詳細過程。 實現右鍵…

??????????????如何使用函數指針來調用函數

在C和C編程中,函數指針是一種特殊類型的指針,它指向一個函數而不是一個變量。使用函數指針可以動態地調用不同的函數,這在實現回調函數、事件處理、策略模式等場景中非常有用。 以下是如何定義和使用函數指針來調用函數的步驟: 定…

KEGG條形圖繪制

原始數據 setwd("C:\\Users\\HUAWEI\\Desktop\\proteomic_WGCNA\\bacteria\\Eggnog\\KEGGhun") library(ggplot2) library(cols4all) dt <- read.csv("bacteria_KEGG.csv")dt$KEGG_Term <- factor(dt$KEGG_Term, levels rev(dt$KEGG_Term))#基礎富集…

My Metronome for Mac v1.4.2 我的節拍器 支持M、Intel芯片

應用介紹 My Metronome 是一款適用于 macOS 的專業節拍器應用程序&#xff0c;旨在幫助音樂家、作曲家、學生和任何需要精確節奏控制的人進行練習。無論是進行樂器練習、音樂創作還是演出排練&#xff0c;My Metronome 都能為用戶提供精準的節拍支持和靈活的功能&#xff0c;確…

宇樹科技13家核心零部件供應商梳理!

2025年2月6日&#xff0c;摩根士丹利&#xff08;Morgan Stanley&#xff09;發布最新人形機器人研報&#xff1a;Humanoid 100: Mapping the Humanoid Robot Value Chain&#xff08;人形機器人100&#xff1a;全球人形機器人產業鏈梳理&#xff09;。 Humanoid 100清單清單中…

Part 3 第十二章 單元測試 Unit Testing

概述 第十二章圍繞單元測試展開&#xff0c;闡述了單元測試的實踐與重要性&#xff0c;通過對比其他測試類型&#xff0c;突出其特點&#xff0c;還介紹了單元測試的最佳實踐、避免的反模式以及與測試替身相關的內容&#xff0c;為編寫高質量單元測試提供指導。 章節概要 1…

【Vite SVG 圖標方案:vite-plugin-svg-icons 指南】

&#x1f31f; Vite SVG 圖標方案&#xff1a;vite-plugin-svg-icons 指南 &#x1f4dc; 背景與痛點 &#x1f30d; 前端圖標演進史 1.0 &#x1f5bc;? 圖片圖標 → 2.0 &#x1f3ad; 字體圖標 → 3.0 &#x1f3a8; SVG 圖標傳統方案存在三大痛點&#xff1a; 字體圖標…

go flag參數 類似Java main 的args

兩部分內容 go run test1.go aa -name 123 1. 解析&#xff1a;aa -name 123 2. 解析&#xff1a;name 123 代碼 package mainimport ("log""os" )func main() {log.Println("main ...")if len(os.Args) > 0 {for index, arg : ra…

酒店旅游API:數據交互的隱形橋梁——以攜程API為例

一、API&#xff1a;酒店 和第三方服務無縫連接。 核心價值&#xff1a; 實時數據互通&#xff1a;房態、價格、庫存秒級同步。業務流程自動化&#xff1a;預訂、支付、確認全程無需人工干預。生態擴展&#xff1a;開發者可基于API構建定制化工具&#xff08;如比價插件、智能…

深入理解 JSP 與 Servlet:原理、交互及實戰應用

一、引言 在 Java Web 開發領域,JSP(JavaServer Pages)和 Servlet 是兩個至關重要的技術,它們共同構成了動態網頁開發的基礎。Servlet 作為服務器端的 Java 程序,負責處理客戶端請求并生成響應;而 JSP 則是一種簡化的 Servlet 開發方式,允許開發者在 HTML 頁面中嵌入 J…

【JavaScript】《JavaScript高級程序設計 (第4版) 》筆記-Chapter20-JavaScript API

二十、JavaScript API JavaScript API 隨著 Web 瀏覽器能力的增加&#xff0c;其復雜性也在迅速增加。從很多方面看&#xff0c;現代 Web 瀏覽器已經成為構建于諸多規范之上、集不同 API 于一身的“瑞士軍刀”。瀏覽器規范的生態在某種程度上是混亂而無序的。一些規范如 HTML5&…

AI芯片的關鍵特征

AI芯片是專門為人工智能應用設計的芯片&#xff0c;以下是其應具備的關鍵特征&#xff1a; 強大的并行計算能力&#xff1a;AI任務如深度學習中的神經網絡訓練和推理&#xff0c;涉及大量矩陣運算和并行數據處理。AI芯片需有眾多計算單元&#xff08;如GPU的大量流處理器、ASIC…

go 模塊管理

go version 查看版本 go version go1.21.12 windows/amd64 需要保證:go的版本升級為1.11以上,go mod依賴的最底版本 go env 查看go的環境變量 go env 開啟go mod # 標識開啟go的模塊管理 set GO111MODULE=on GO111MODULE有三個值:off, on和auto(默認值)。 GO111M…

Unity 適用于單機游戲的紅點系統(前綴樹 | 數據結構 | 設計模式 | 算法 | 含源碼)

文章目錄 功能包括如何使用 功能包括 紅點數據本地持久化 如果子節點有紅點&#xff0c;父節點也要顯示紅點&#xff0c;父節點紅點數為子節點紅點數的和&#xff1b; 當子節點紅點更新時&#xff0c;對應的父節點也要更新&#xff1b; 當所有子節點都沒有紅點時&#xff0c…

使用API有效率地管理Dynadot域名,為域名部署DNS安全拓展(DNSSEC)

關于Dynadot Dynadot是通過ICANN認證的域名注冊商&#xff0c;自2002年成立以來&#xff0c;服務于全球108個國家和地區的客戶&#xff0c;為數以萬計的客戶提供簡潔&#xff0c;優惠&#xff0c;安全的域名注冊以及管理服務。 Dynadot平臺操作教程索引&#xff08;包括域名郵…