Skip to content

Latest commit

 

History

History
187 lines (135 loc) · 16.3 KB

File metadata and controls

187 lines (135 loc) · 16.3 KB

記憶體與執行速度調整

2026-10-03(第四輪):掃描、解析、排序與更新輪詢

再次盤點自有函式,包含新加入的更新服務。完整範圍、取捨、基準與重跑方式見第二次函式檢查報告。

  • 2,000 個不支援檔案的掃描配置量由 690 KB 降至 274 KB;先判斷檔名,再為需要的項目組合路徑。
  • 64 段 HLS 清單解析由 96.7 KB 降至 28.5 KB 配置,保留原有單行限制、格式與錯誤行為。
  • 更新輪詢使用精簡快照,重用完整發行資訊;相同下載/更新狀態不再替換 React state。
  • 4,999 列含空白數值的表格排序由 4.535 ms 降至 0.724 ms;已排序數值欄位使用無排序工作區的快速路徑。

前端 161 項、Go 205 項一般測試及 3 個 fuzz 種子套件通過;race、Go vet、TypeScript/Vite、Wails production 編譯及 macOS 12 arm64 目標檢查通過。前端 JSX/CSS 與本輪修改前一致。上述為受控函式基準,非整體 App 或長時間 RSS 量測。

2026-10-03(第三輪):函式層級最佳化

本輪完成自有 Go、前端及建置工具的函式盤點,維持 UI、操作、功能與認證方式。完整範圍、函式清單說明、量測及重跑方式見函式檢查報告。

  • 掃描及項目建立共用副檔名結果;壓縮檔建樹只為新節點建立路徑。5,000 筆共用目錄的建樹基準由 2.105 ms/60,052 次配置降至 0.937 ms/59 次配置。
  • 換行正規化使用單一輸出配置;UTF-16 直接解碼,省去 code unit 與 rune 中間資料。代表性 ASCII/中文輸入配置量分別由 2.25/1.87 MB/op降至 0.180/0.336 MB/op。
  • HLS 下載共用分段緩衝,線性選流並精簡屬性解析;256 個分段的純複製配置由 64.01 MiB/op降至 268 KiB/op。
  • 音訊預計算頻譜位置並重用振幅陣列,72 柱計算由 5.77 µs降至 1.78 µs;字幕改為單次選出最佳候選。
  • 主視窗只收集必要的選取 ID;相同文件的上色結果在元件內重用。1,000 行程式碼再次渲染的函式基準由 14.83 ms降至 1.28 ms。

前端 146 項、Go 186 項一般測試及 2 個 fuzz 種子套件全部通過;Go race、額外文字 fuzz、TypeScript/Vite、Go vet、原生編譯及 macOS 12 目標檢查通過。App/播放器 JSX 與 Canvas 繪圖結果對照原版保持一致。

上述數據是受控函式基準,配置量不是常駐記憶體;不包含實際網路下載、磁碟掃描或原生 WebView 的長時間 RSS。新增工作區的保留時間及完整驗證界限列於報告。

縮圖工作區

  • 虛擬網格只掛載可視列及前後兩列,保留「載入更多/全部載入」與跨捲動選取。
  • 前端縮圖 LRU 同時限制 200 筆及 16 MiB(依 UTF-16 字串長度保守估計);未開始的離屏請求直接移除,最多同時 3 個後端請求。
  • 後端縮圖直接串流解碼,只暫存讀取尺寸所需的前綴;同時解碼的總像素不超過 5,000 萬。
  • 磁碟縮圖使用 LRU 索引;每次寫入維持最多 1,200 筆、256 MiB,只在初始化掃描目錄。外部刪除快取時同步移除索引。
  • 縮圖版本包含來源大小與修改時間;macOS 另比對 inode 與 change time。解碼期間來源變更時不寫入舊版本快取;快取讀取在同一 FD 上限制最多 16 MiB。
  • 影音解壓及轉檔快取比對來源檔案識別、大小、修改時間;來源更新時重建,已開啟的舊讀取器仍可完成讀取。
  • 媒體清理先取消準備與複製,再等待項目鎖釋放;HTTP 只持鎖至成功開檔,串流讀取不占用準備鎖。
  • 像素預算不是程序 RSS 上限:解碼器工作區、16-bit 圖片及 GC 尚未回收的物件仍會占用記憶體。仍使用 Go 完整解碼,尚未加入平台限定的降採樣解碼器。

主圖傳輸

LoadImage* 的 ImagePayload.dataUri 可為 /image/<id>?v=... 本機網址。保留欄位名稱以維持前端結構;不要假設一定是 Base64。

本機圖片由 HTTP 串流傳輸,保留 128 MiB 檔案與 5,000 萬像素限制,GET/HEAD/Range 與 ETag。端點只接受已註冊的圖片 ID。壓縮檔圖片仍有完整驗證緩衝區,最多並行 2 筆;原圖不再經由 Wails 傳輸 Base64。

前端只解碼目前顯示的圖片,切圖取消舊要求,背景僅預備相鄰圖片的網址/標頭。剪貼簿仍可輸出 PNG,只有文字備援時才轉回 Data URI。

壓縮檔

  • ZIP:LRU 最多 4 個中央目錄索引;每個最多 20,000 個項目與約 8 MiB 的標頭資料估計值。超限時不保留索引。
  • TAR/TGZ:最多 2 份、每份最多 256 MiB 的私有暫存內容與 20,000 個索引項目。第一次讀取建立索引會多花時間與磁碟 I/O,後續以位移讀取;超限或稀疏檔案回到原串流方式。暫存檔不依壓縮檔中的路徑解壓至目錄。
  • 大小、修改時間或檔案識別改變時快取失效;清空圖庫及結束應用程式會清理快取。使用中的 reader 關閉後才釋放其資源。

圖庫

展開狀態與選取獨立儲存,不觸發整棵樹的 JSON 寫入。掃描約每 100 ms 批次更新畫面,同批結果只遍歷一次樹;未變更分支保留原參考。忽略未支援的檔案時不額外取得檔案資訊。

2026-10-03(第二輪):掃描佇列、工作區篩選及小型讀取

本輪繼續保留 UI、操作、功能與認證方式,沿用上一輪修改。

  • 目錄掃描改為優先/一般兩個 FIFO 佇列,路徑只分類一次,避免每次加入子目錄後重新排序全部待掃描路徑。以固定 256 筆的分塊保存,取出後清除該路徑參照,清空的區塊可回收。Finder 指定路徑仍優先,各群組順序、進度與取消檢查維持不變。
  • 工作區無篩選時直接複製清單,保留每次篩選結果的新陣列身分;搜尋改為欄位逐一短路比較,不建立每筆欄位陣列,也不保存持久搜尋字串快取。
  • 零選取時不再建立整個圖庫的有效 ID 集合;非空選取只保留與選取相交的 ID。範圍/全選不先建立中間 ID 陣列,批次刪除以集合查詢取代逐筆 includes,保留選取插入順序及部分失敗行為。
  • CSV/TSV 使用重用的語系比較器,保留原有數字優先及自然排序。沒有排序的搜尋只保留前 1,000 筆,在第 1,001 筆符合時顯示原本的截斷提示;需要排序時仍處理全部匹配列。已由篩選產生的新陣列可直接排序,避免額外複製。
  • 後端在大小提示為 1 MiB 以下時預配置讀取緩衝。提示只影響容量,不決定讀取長度;仍完整讀至 EOF,保留大小哨兵、ZIP CRC、取消與檔案大小失準處理。未知或較大提示使用原有標準讀取方式,避免預先配置大量記憶體。

受控基準:

情境 調整前 調整後
2,500 待掃描目錄、帶優先目標,純佇列管理 801 ms 0.465 ms
50,000 筆無篩選清單時間 0.888 ms 0.049 ms
同上,暫時 heap 增量 1.24 MB 0.40 MB
50,000 筆搜尋無匹配,暫時 heap 增量 15.32 MB 8.41 MB
空選取重新整理,暫時 heap 增量 3.02 MB 約 1 KB
10,000 個選取刪除 5,000 個的集合更新 62.60 ms 0.500 ms
4,999 × 24 表格,文字排序 107.51 ms 9.58 ms
同一表格,大量匹配、無排序篩選的 heap 增量 5.17 MB 1.07 MB
1 MiB 一般項目讀取配置 2.23 MB/op 1.06 MB/op
128 KiB 縮圖快取讀取配置 303 KB/op 141 KB/op
1 MiB 圖庫快取讀取配置 3.28 MB/op 2.11 MB/op

取捨與量測範圍:批次刪除增加約 67 KiB 暫時 heap,以換取線性集合查詢;40,000 目錄、無優先目標的佇列基準亦增加約 2.1 MB 暫時 heap,避免反覆搬移陣列。分塊在出列後釋放路徑及空區塊,不保留完整歷史。這些 heap 差額受 Node GC 影響,並非精確配置總量或原生 App RSS;佇列基準不含磁碟掃描及畫面更新,不能推論實際掃描等比例加速。8 MiB 讀取配置維持原路徑,約 17.06 MB/op。

重跑本輪基準:

cd frontend
node --expose-gc benchmarks/scan-queue.mts
node --expose-gc --max-semi-space-size=256 benchmarks/workspace.mts
node --expose-gc benchmarks/structured-table.mts
cd ..
GOTOOLCHAIN=go1.26.6 go test ./internal/app -run '^$' -bench 'BenchmarkBounded' -benchmem -benchtime=300ms

本輪驗證:

  • 新增 19 項一般回歸測試(前端 15、Go 4)。前端 131 項、Go 178 項一般測試及 1 個 fuzz 種子套件全部通過,無跳過;Go 使用 race detector,internal/app statement coverage 73.8%。
  • TypeScript/Vite production build、Go vet、desktop/production 原生編譯通過,arm64 最低 macOS 版本維持 12.0。App JSX 與修改前逐段比對一致。
  • 掃描驗證一般 FIFO、Finder 優先、略過封存節點、取消及分塊邊界;篩選驗證 Unicode、結果身分、選取順序、部分失敗及重複結果失效;表格結果逐項對照原版;讀取包含大小提示失準、尾端 CRC 及最後一次讀取的取消。
  • 修改前保留 .bak,完成後清除本輪備份、建置/測試輸出及驗證專用 Go 快取。保留既有 App/DMG、模型與上一輪未提交修改;未同步 GitHub。

驗證界限:未量測原生 WebView 長時間 RSS;FFmpeg/ffprobe 回歸採受控替身,未重新進行原生介面人工操作或完整發行封裝驗證。基準與一般配置最佳化不構成整體 App 效能保證。

2026-10-03(第一輪):減少重複遍歷與暫時配置

本次維持 UI、操作、功能、格式支援及安全限制;只調整內部資料整理與工作區重用。

  • 圖庫更新採延遲複製,未變動的 images/children 不建立替代陣列;批次搬移只遍歷一次樹,每個目的地排序一次。成功/失敗回報、選取清理及同名穩定排序保持原有語義。
  • 顯示樹保留未變動分支,WeakMap 快取可見節點與分類統計。節點更新必須維持 immutable;快取以弱鍵保存,不阻止已丟棄樹被 GC 回收。
  • 工作區維持根節點優先的順序,導覽維持子節點優先的順序。收集結果直接追加,不再每層複製整份子樹陣列;根目錄清單共用既有結果。
  • 摺疊節點的選取標記一次檢查所有選取 ID。圖片預取仍依 +1、−1、+2、−2 的圖片順序,只收集附近項目,不再每次切圖建立完整導覽與篩選陣列。
  • 檔名排序直接比較小寫 rune,避免每次比較建立兩個小寫字串;保持 strings.ToLower 的 Unicode、無效 UTF-8 與穩定排序行為。
  • 重複內容偵測以輸入下標保存候選,只有相同大小時才建立候選陣列;同次操作共用 32 KiB 雜湊讀取緩衝,確認重複後才建立回傳項目。
  • 磁碟縮圖快取命中時移動原 LRU 節點,更新大小差額,不再移除後重新配置節點。PNG 壓縮工作區可重用;使用後清除縮圖像素與輸出 buffer 的參照,閒置工作區仍可由 GC 回收。原圖已符合縮圖尺寸時直接複製,省去雙線性縮放的中間陣列;代表性像素格式的 PNG 輸出與原流程逐 byte 相同。

受控基準(同一測試資料;數值取代表性量測,時間會受背景負載影響):

情境 調整前 調整後
62,480 筆圖庫資料整理時間 7.52 ms 3.87 ms
同上,暫時 heap 增量 32.89 MB 12.60 MB
40,000 項目圖庫批次搬移 100 項 28.16 ms 1.50 ms
20,000 個不同大小項目去重配置 5.82 MB/op 1.18 MB/op
256 個同大小檔案去重配置 8.87 MB/op 0.385 MB/op
5,000 個 ASCII/Unicode 名稱排序配置 4.93/7.40 MB/op 232 B/op
256×256 無須縮放的縮圖時間 4.82 ms 4.05 ms
同上,配置量 4.26 MB/op 1.33 MB/op
640×480 縮至 280 的配置量 7.27 MB/op 6.99 MB/op
縮圖 LRU 命中維護配置(不含磁碟 I/O) 72 B/op 0 B/op

Node heap 增量是強制 GC 後呼叫前後的近似差額,不是精確配置總量或程序 RSS;部分無命中操作主要減少配置,未保證每次執行較快。Go B/op 是基準記錄的配置量。這些結果不代表整體 App 等比例加速或常駐記憶體降幅。

可重跑:

cd frontend
node --expose-gc benchmarks/library-view.mts
node --expose-gc --max-semi-space-size=256 benchmarks/library-tree.mts
cd ..
GOTOOLCHAIN=go1.26.6 go test ./internal/app -run '^$' -bench 'Benchmark(LibraryNameSort|DuplicateDetection|ThumbnailRenderReuse|ThumbnailUnscaledReuse|ThumbnailDiskCacheHit)' -benchmem -benchtime=300ms

本輪驗證:

  • 前端 116 項測試通過;Go 174 項一般測試及 1 個 fuzz 種子套件通過,無跳過,使用 Go 1.26.6 race detector。internal/app statement coverage 73.6%。
  • 本輪新增 18 項一般回歸測試及 1 個 fuzz 測試;排序另以 10 秒、約 10 萬組 fuzz 輸入比對原有 strings.ToLower 行為。
  • TypeScript/Vite production build、Go vet、desktop/production 原生編譯通過,最低 macOS 版本維持 12.0。
  • App 的 JSX 結構逐段比對未變;不同圖庫形狀的可見樹、兩種遍歷順序、分類統計、祖先 ID、選取、預取及批次搬移均與原行為比對。
  • 縮圖涵蓋 6 種 PNG 像素格式、JPEG/GIF、透明與不透明圖片、多個尺寸及 12 個並行工作,對照原縮放流程輸出。
  • 修改前建立 .bak;完成後清除本輪備份、測試輸出及驗證專用 Go 快取。未改 UI 樣式、認證或建置流程,未同步 GitHub。

驗證界限:這些基準沒有量測原生 WebView 長時間 RSS;PNG 工作區重用減少累計配置,閒置工作區可能存活至後續 GC。FFmpeg/ffprobe 回歸使用受控替身,未重新完成原生介面人工操作或發行包簽章驗證。

前期驗證記錄(2026-09-19~2026-09-21)

  • npm --prefix frontend run build
  • npm --prefix frontend test:46 項通過,包含虛擬網格、縮圖容量與取消、圖片傳輸取消、批次樹合併、深層 JSON、移動來源對應、操作釋放、音訊/字幕非同步取消及 FFmpeg 建置前檢查。
  • go test -race ./...:111 項通過,包含跨磁碟搬移與取消、媒體生命週期、圖片 HTTP 端點、安全限制、ZIP/TAR 快取失效、使用中淘汰與解碼預算測試。
  • Chromium + 模擬 Wails 圖庫:10,000 張圖片,1500×950 視窗頂端 18 張卡片、底端 16 張;選取、來回捲動、篩選、縮放視窗通過,沒有 pageerror。後端縮圖呼叫峰值 3。展開目錄後完整圖庫寫入次數不變。這不是 macOS 原生 WebView 的 RSS 量測。
  • Apple M4、Go 1.26.4,5,000 個 ZIP 項目、讀取最後一項的合成微型基準:重新開啟/搜尋約 490 µs、1,272,527 B/op;索引命中約 3.09 µs、737 B/op。這僅反映暖快取查找,不能推論整個程式快 158 倍。

重跑 ZIP 基準:

go test ./internal/app -run '^$' -bench BenchmarkZIPEntryLookup -benchmem -benchtime=300ms

3D 預覽(1.26.1004 build 0945)

3D 渲染維持既有材質、畫質及滑鼠操作。格式解析器只在選取對應模型時載入;模型輸入優先直接填入單一緩衝區,整數百分比改變時才更新進度。共用材質只檢查一次,靜態場景完成後固定世界矩陣;畫布尺寸與像素倍率相同時不重新配置。取消預覽時立即清空場景集合,延遲完成的貼圖也會回收。

在 frontend 執行:

node --expose-gc benchmarks/model-preview.mts
合成案例 修改前 修改後
64 MiB 串流輸入的 ArrayBuffer 用量 約 128 MiB 約 68 MiB
相同輸入的進度通知 1,024 次 101 次
5,000 個共用幾何/材質網格的檢查中位數 4.13 ms 0.82 ms

基準保留修改前的讀取與檢查實作作為比較;輸入每區塊 64 KiB,並定期允許 GC,模型檢查則先暖機、量測五輪後取中位數。記憶體只衡量輸入 ArrayBuffer,不包含整個 App、WebKit、模型解析、貼圖解碼或 GPU;時間與模型內容及硬體有關,不能推算整體 App 的等比例加速。

13 組原生 macOS WebKit 比較涵蓋七種格式、點雲、不受光材質、正常與缺少貼圖及受限資源;修改前後畫素一致,旋轉、平移、縮放、重設與快速取消通過。正式打包另驗證 HTTP 與 wails:// 的按需載入及相同操作。