疾徐與除錯
欲腳本之行,疾而且穩:熱路徑之守則、記憶體之衛生,暨事出之際所當觀者,皆在焉。
疾徐之模型
每幀每實例之費,其構如次:
| 環節 | 所費 |
|---|---|
| 快照搬運(宿主 → 模塊) | 唯一所迫之 Java 穿越:宿主以復用之建構器,書 POD 快照於共享頁 / 直接緩衝 |
數據之讀(Vehicle / Pids / …) | 尋常記憶體之讀,零費 |
| 繪製記錄之書 | 之區內 bump 分配,零分配零裝箱 |
像素光柵(Gfx2D) | 純 C++ 之環;src-over 不透明有快捷之途 |
| 宿主回放 | 與 JS 同一渲染之途;紋理上傳惟搬髒矩形 |
Api 之呼 | JSON 編碼+反射+JSON 解碼之往返——費巨 惟作低頻之通道 |
熱路徑守則
- render 之內,勿近
Api。高頻之數據,盡在快照;高頻之繪製,盡行乎記錄之流。JS 之世,週期性 GC 之頓挫,正「每幀每車一反射之呼」所致也。 - 資源惟建於
create:模型也,紋理也,Java 物件之柄也,回呼也——既建,則存諸State;render惟用之而已。 - 勿逐幀讀資源、行 HTTP:網路之事,入諸
BackgroundWorker;所得者,納諸君自家同步之緩存;render 則讀其緩存。 - 紋理惟內容既變乃上傳:靜態之景,一繪足矣;動態之內容,以
push_clip限其重繪之域,使髒矩形惟覆真變之條。 - 逐物件而錯其相:多實例輪播、閃爍之動,勿同幀而齊發——以參差之調度,散髒區於諸幀(以
in_game_time()或game_time_millis()為鐘)。 - 字串暫物,用之宜節:
StrView相較,免其抄寫;確須拼接,則慎std::string之分配(短串有 SSO,免乎分配)。
記憶體與延遲回收
宿主側記憶體之紀(腳本作者知之可也;其利則 SDK 自蒙之):
- 五輸出之區者,每模塊一份,幀間復用;像素之區初 1 MB,按需而增(其上 16 MB),尖峰既過,則確定收縮而復歸下限——每模塊 16 MB 固定駐留之弊,不復有焉。
- 實例去視錐而不毀(保其暖態;重入於鏡,則零重建);誠去乎客戶端車輛之列者,約五秒乃除役。
- 大塊之釋,行乎
defer_free(ABI 10):render/dispose之內既死之兆級緩衝,付諸宿主後臺回收之線程——免free之全費累乎當前之幀,且免大 GC 安全點之待。其約曰:塊必既死,必無析構,此後必無線程(宿主回放亦在數焉)復觸之。SDK 像素之區之收縮,已自遵之;君自有之大緩衝,循同規而呼host->defer_free可也;宿主過舊(其槽為 null)者,同步 free 亦可。
觀測與日誌
| 所觀 | 所在 | 內容 |
|---|---|---|
| 模塊 census | logs/latest.log 啟動之段 | 已載模塊之數與其類;傳輸通道摘要之行(含 transport: 之樣:shared-memory / panama-ffm 之屬)——所以證 shm / FFM 誠已生效、有無靜默降級也 |
| 載失之由 | census 行+除錯之模 | 一側(JS 或 C++)缺焉 / 載敗焉,則惟略彼側而留其示;餘側行如常 |
| 崩潰防護 | latest.log | native script faulted: code=… module disabled——模塊見禁之確由 |
| 清掃之流 | latest.log(每分鐘一行) | 實例銷毀節奏之彙錄,實例壽命之行,得以徑觀焉 |
| 上傳位元組之數 | GraphicsTexture::last_upload_bytes() | 於君之碼中誌之——髒矩形之策效否,一覽而知 |
庫既改矣,按 F3+T(或模組「重載全部 MTR 腳本」之快捷鍵),即可重載 C++ 腳本——卸載與復尋,皆行乎全程,無須重啟遊戲也。
JVM 參數
| 參數 | 預設 | 所司 |
|---|---|---|
-Djcm.nativeIdleMillis | 90000 | 實例猶存而久未渲染者,逾此毫秒之數乃釋;0 者,不依時限而釋也 |
-Djcm.nativeIdleMax | 32 | 暖實例之上限;踰之者,以最久未渲染者先釋。0 者,不設其限也 |
-Djcm.ffm.disable | 關 | 除錯之關:禁 Panama FFM 載入之途 |
實例之除役與銷毀,別有每 tick 之預算焉(預設二,舊者先出);世界既卸,維度既遷,或連接既斷,則一舉沖刷之。
常見之問
模塊全然不載,何也?
- 先察所用者,Release 之 jar 抑 Complete Build 之 jar——速成 CI 之產物,不含原生橋,日誌必書
native bridge unavailable(非君模塊之咎也)。 - 次察平臺之目:當前系統,惟載所應平臺之庫;無副檔名之 stem 宣告,自展為諸平臺之路(見打包)。
- 復察
ID與宣告條目之id,逐字相合否。 - 終察 ABI:宿主所受,6 至 11 也;ABI 8+ 之庫,須 2.3.0-beta-2.yanyang.7 及以上之宿主。
屏現占位之框(tofu),何也?
CJK 字形,宿主字體不覆其碼位,則退為占位之框——以資源字體之 id,傳於 Text::font() 與 Gfx2D 之構造(如 jsblock:shanghai),或察所用字體之集,果含此諸字否。
間或失幀,何也?
- 先觀其每幀重繪全屏否:靜態之內容,一繪足矣;動態之內容,clip 條帶而重繪之;以
last_upload_bytes()驗之。 - 次觀多實例同幀齊動否:輪播也,閃爍也,開門之動也,逐物件而錯其相。
- 終察 render 之內,有無
Api之呼(兼其間接者:ctx.set_auto_z_ordering諸一二上下文之法,於 ABI 8+ 將轉發一遭)。
Windows 上所行與他處異,何也?
ABI 6 之前古版,嘗恃「零填充之記憶體可徑作物件用」——此恰惟於 MSVC 布局之下,倖存焉耳。今 SDK mtrInit() 之約,已根治之;君若自撰宿主,務於既配狀態塊之後,呼 mtrInit()。
返:文檔之首。