当前位置: 首页>C++>正文

lua編程軟件,QQ郵箱記事本模塊Lua實現小結

lua編程軟件,QQ郵箱記事本模塊Lua實現小結

QQ郵箱是一個除了收郵件和發郵件的基本功能之外,具有其它一些小的辦公功能的郵箱客戶端。其中記事本是辦公功能之一。
但是集成了記事本等小功能的郵箱,體積較大。為控制客戶端體積,需要將非基本功能的一些功能模塊腳本化,不編譯到App當中,達到控制App體積,修復和升級方便的目的。
本文包括3個部分:

  • 原理簡介
  • 優化經驗
  • 教訓

原理簡介

Lua作為一門腳本語言,借助Lua腳本引擎和Lua運行庫,來解釋執行Lua腳本。我們選擇Wax作為Lua引擎,來執行Lua。它利用Objective-c Runtime的特性,在Lua腳本中調用OC的類和方法。Wax由probablycorey創建,目前由阿里團隊負責維護。
Wax引擎原理在于:
Wax包含一個Lua的解釋器和運行庫,從而能解釋執行標準Lua腳本;
Wax擴充了Lua的語法,為Lua調用OC類及OC類動態添加方法提供了基礎。
使用Lua實現的優勢(參考此鏈接):

  1. 自動垃圾收集 無需手動創建對象,即無需用alloc方法進行對象的初始化工作;
  2. 更少的代碼 無需頭文件,不用static類型、數組和逐字化聲明字典;
    使用Lua能調用每一個Cocoa,UITouch,Foundation等類和框架;這種調用OC類的能力也為功能模塊使用Lua腳本實現提供了基礎。
  3. Lua使用closure來替代OC中的Blocks
  4. 內置正則匹配庫
  5. 超簡單的HTTP 請求
  6. 動態下發和執行
    Lua代碼可以作為資源文件下發到app端,然后在app端進行動態執行。從而能夠減少app安裝包的體積,并能動態發布和維護代碼。郵箱的記事本模塊目前采用此模式,后面會詳解。

優化經驗

1. 多線程和鎖

lua編程軟件。分析Lua引擎和Wax框架,鎖會在下述情況下產生:
a. Lua底層api對運行上下文lua_State加的鎖
b. Wax框架在C和Lua數據交換時,為保證線程安全所加的鎖
解決方案:
使用Lua協程,或者用Lua協程配合iOS的GCD框架,使得父協程和子協程在不同的空間中運行,從而支持競爭式多協程。
Lua框架本身并不支持多線程,但OC中很多情況下得使用多線程,所以在OC轉換成Lua的過程中,需要讓Lua支持多線程才能做到和原生OC寫的效果一致。解決方案是利用協程,配合GCD達到多線程的效果。
圖1. Lua協程
圖1. Lua協程

2. 自動生成 OC調用Lua的代碼

在混合了Lua和OC的項目中,很多時候我們是在Lua代碼里去調用OC的類和方法,但難以避免需要在OC代碼里面調用Lua的函數。我們需要借助lua_State來實現。為了便于調用,我們封裝了一個類:WaxOCHelper.m用來進行OC調用Lua。
圖2 自動生成的OC調用Lua的函數示例
圖2 自動生成的OC調用Lua的函數示例
我們實現了一個腳本,只需要寫一個聲明函數的頭文件,即可生成圖2的代碼。實現時,根據函數參數類型和個數,以及函數的返回類型,對應生成圖2中316-322行的代碼。其中316行的name參數:”LuaNoteManager”為指定的Lua函數所在的文件名,317行的name參數與312行的函數同名。因此只需要寫頭文件,即可生成對應的實現文件。

3. Lua的調試

Xcode本身并不支持Lua的調試,借助Lua的插件或者Lua的IDE,可以進行Lua的調試。我們使用的是ZeroBraneStudio,來進行Lua的調試。
3.1 本地調試
在需要調試的函數文件代碼頭部添加:

require('mobdebug').start()

lua可視化腳本編輯器。即可進行該代碼文件的調試。注釋該行代碼,即可取消對該文件的調試:

-- require('mobdebug').start()

3.2 遠程調試
Wax里面有一個Lua debug庫:mobdebug,利用它可以實現Lua代碼的調試。原理如下:
a. 使用require(‘mobdebug’).start()函數,會始化調試用的debug協程,并設置Lua的hook參數。同時會首先使用socket對象與服務器建立連接,進行數據交換;
b. 當App執行到start()的下一行時,會進入hook函數,hook函數在斷點行數判斷到該行應該中斷,會喚醒debug協程,等待debug指令(進入receive()函數)。
c . 輸入下述命令:

setb fileName lineNumber

可以對文件fileName的lineNumber設置斷點
d. 若想繼續執行app代碼,發送run命令,debug協程執行mobdebug.handle(“run”),并發送”200 OK”后,自己掛起(coroyield())debug協程。
e. App再次進入斷點調試模式,debug協程會被重新喚醒,發送”stack”命令可以獲取當前的堆棧信息。
通過node js,可以建立一個socket服務器,與app進行通信。從而基本實現Lua的遠程斷點調試,目前還在完善Lua的遠程調試當中。
調試流程如下:
圖3 Lua遠程調試流程圖
圖3 Lua遠程調試流程圖

4. 數據庫的操作優化

lua腳本編寫教程詳細。使用Lua提供的元表(Metatable),來代替對OC對象的屬性進行反射操作,來相應提高操作數據庫中的對象的操作性能。
在進行QQ郵箱記事本模塊的Lua腳本化過程中,很多環節需要進行記事本的數據庫操作,如果使用OC的屬性讀寫函數對記事本數據庫進行讀寫等操作,步驟較多:
1)反射note對象的所有方法->2)通過字符串比較函數得到相應的方法->3)反射得到相應方法的所有參數類型->4)將Lua的參數轉換成OC對應的數據類型->5)組裝方法和參數,動態調用OC方法->6)返回OC方法的返回值到Lua。
而使用元表進行操作,只需調用Lua中元表的操作,對table的鍵值進行讀取或設置值,節省了反射的性能損失。
比如:記事本類Note有個表示記事本內容的content屬性,使用OC設置時,需要調用note:setContent()方法來操作,而使用Lua的元表操作,即可用”note.content=”XXX”“來完成。
在Lua中,對Lua的元表進行key值讀取,分別是調用__newindex元方法對表更新,__index方法來進行表訪問。
引用我們組一起進行Lua腳本化功能開發的同事william的測試結果,使用原生的OC方法,Lua的元方法,OC和Lua的反射三種操作,對有23個屬性的Note對象的數據庫表(對應有23列)進行10000次save,read,delete操作,性能對比如下表1所示。
表1 數據庫優化
從表1中可以看出,數據庫Lua元表對象的操作,基本達到和OC原生操作的性能水平,而使用反射調用原生的方式,會有明顯的性能損耗,尤其在delete操作更是增大了3倍之多。

5. Lua代碼的下發和更新

當版本發布或維護功能模塊時,我們需要上線Lua代碼,并更新app本地的Lua,實現步驟和原理如下:
1. MD5計算
計算新下發的Lua對應的App版本號是否與自身相符合
2. 解密檢驗
獲取下發的加密Lua腳本,并用私鑰解密得到原始的Lua腳本,然后計算下發的Lua腳本字符串的MD5值,是否與本地存儲的Lua腳本的MD5值一致,不一致時,對相應版本的Lua腳本進行更新。

上線Lua配置流程:
自動轉化Lua代碼為下發內容字符串,每個Lua文件對應一個字符串。將下發內容添加到Lua配置文件當中配置Lua腳本我們使用的Lua腳本配置包括以下幾個關鍵部分:Lua文件概要信息:
圖4 Lua文件概要信息
圖4 Lua文件概要信息
圖4中featurecount字段表示目前有兩份針對不同版本下發的Lua配置,實際單個App會獲取到相應版本的配置文件;
codecount字段表示所有Lua文件的個數,若一個Lua源代碼有針對2個版本的不同文件,算2個。
Lua文件名,內容,支持的起始版本:
圖5 Lua配置信息
圖5 Lua配置信息
圖5中124行表示文件序號,內容為CodeInfo后加序號,因為Lua代碼存在代碼依賴,所以各Lua代碼間順序不能顛倒;
圖5中125行表示文件名;
圖5中126行代表轉換的Lua文件內容,為一字符串;
圖5中127行-130行表示支持的版本范圍,versionbegin代表支持的最低版本,versionend代表支持的最高版本。其中ipad開始的字段值表示支持的iPad版本。版本號的”.”在此用”0”代替,所以50103代表版本號5.1.3.

lua腳本生成器、Lua代碼的下發配置
圖6 Lua代碼下發配置
圖6 Lua代碼下發配置
圖6中216-219行表示配置1,219行表示下發的文件序號,順序排前的優先下發。灰度上線并測試無誤后,加密后逐步下發到現網用戶。

教訓

1. nil 值的檢查 

Lua中調用nil對象或參數會導致crash,所以務必檢查,確保對象和參數不是nil值
圖7 nil值檢查
圖7 nil值檢查

2. 數組索引起始值

Lua中,數組的起始值是1。取長度時,直接用#操作符號。
圖8 數組索引
圖8 數組索引

3. block

圖9 block
圖9 block
上圖9中,紅框內的參數字符依次為: block返回值類型,block參數類型(99行function()括號中的參數)。需要注意的是Lua沒有類的概念,OC類使用 id 類型替代。

4. 中文字符串求長度

對于純英文的NSString字符串,使用其length屬性即可,但是對于包含有中文的字符串,使用UTF8編碼時,1個中文字符占3字節,此時使用length屬性獲得的值偏大。
參考此博客方案:,可解決這個問題。
圖10 求中文字符串長度
圖10 求中文字符串長度

https://www.nshth.com/cplus/338889.html
>

相关文章:

  • lua編程軟件
  • lua可視化腳本編輯器
  • lua腳本編寫教程詳細
  • lua腳本生成器
  • QQ郵箱記事本照片亂碼
  • QQ郵箱寫記事本別人能看嗎
  • lua寫入文件
  • lua腳本模板軟件
  • github 免費節點,BUMO:超級節點共建接口
  • 學習html/css基礎的重點筆記
  • 企業郵箱怎么群發郵件,企業會員郵件群發解決方案
  • esfp光模塊,闡述一下ecshop各模塊的功能_【光電通信】40G QSFP+ LR4 光模塊的設計與實現(一)...
  • lua編程軟件,QQ郵箱記事本模塊Lua實現小結
  • centos7.6鏡像下載,centos(7.9) minikube(v1.28.0) kaniko 構建鏡像
  • 計算機畢業設計ssm企業部門報銷管理g9d62系統+程序+源碼+lw+遠程部署
  • 鮑森詹森實驗過程,Ornstein-Uhlenbeck過程
  • 嵌入式的發展趨勢,我理解的嵌入式幾個發展方向
  • 51開發板,IMX6ULL_PRO嵌入式開發板介紹
  • 嵌入式軟件工程師,2023屆秋招內推指南|嵌入式開發|軟硬件
  • 剛畢業的大學生適合做什么工作,今天我的就業班的生活開始啦~~~
  • C語言-基礎知識練習習題1
  • 什么監控攝像頭最清晰,計算機為什么找不到攝像頭,為何電腦里找不到攝像頭設備?
  • 網易支付登錄,微信登陸和支付
  • 人工智能自我進化,復雜性思維中文第二版 十一、進化
  • firebase,Firebase 教程: iOS A/B 測試
  • mongodb可視化管理工具,Impala入門筆記---比Hive強大
  • 世界只是一個程序,程序的世界里,短暫的放空
  • 如何用爬蟲爬取網頁上的數據,新聞爬蟲及爬取結果查詢網站的搭建(一)
  • 爬蟲網站,新聞網站爬蟲及結果查詢
  • 深度卷積神經網絡,深度KWeaver:價值驅動,認知智能走向開源共創
  • sci論文翻譯神器,SCI科技論文英語翻譯的一點個人心得
  • 協議的定義,連接跟蹤TCP協議狀態轉換
  • 洛谷 T284709 怨念(resent)
  • 1330 小青蛙跳臺階
  • 動態規劃解決小青蛙跳臺階問題
  • 代碼記錄丨小青蛙和漢諾塔
  • 小青蛙爬井
  • 【基礎】小青蛙回來了