1. 程式人生 > 實用技巧 >iOS-OOM(out-of-memery)

iOS-OOM(out-of-memery)

Jetsam管理的一種crash機制,通過Signal無法捕捉到Jetsam,iOS不支援交換空間,無RAM和DISK之間的對映,這是因為移動端大多數裝置均為快閃記憶體。
Jetsam crash日誌

{"bug_type":"298","timestamp":"2020-10-19 11:27:59.22 +0800","os_version":"iPhone OS 14.0.1 (18A393)","incident_id":"48A5344C-34D3-4FD1-BAF3-EAFBC1F15842"}
{
  "crashReporterKey" : "ed5786382fe57f1c8c847aa1995b4ae301ff1eea",
  "kernel" : "Darwin Kernel Version 20.0.0: Fri Aug 28 23:07:00 PDT 2020; root:xnu-7195.0.46~9\/RELEASE_ARM64_T8020",
  "product" : "iPhone11,6",
  "incident" : "48A5344C-34D3-4FD1-BAF3-EAFBC1F15842",
  "date" : "2020-10-19 11:27:59.22 +0800",
  "build" : "iPhone OS 14.0.1 (18A393)",
  "timeDelta" : 89,
  "memoryStatus" : {
  "compressorSize" : 66687,
  "compressions" : 1574450,
  "decompressions" : 920590,
  "zoneMapCap" : 1441710080,
  "largestZone" : "vm pages array",
  "largestZoneSize" : 11223040,
  "pageSize" : 16384,
  "uncompressed" : 177283,
  "zoneMapSize" : 127418368,
  "memoryPages" : {
    "active" : 54456,
    "throttled" : 0,
    "fileBacked" : 32811,
    "wired" : 52390,
    "anonymous" : 75798,
    "purgeable" : 1361,
    "inactive" : 53082,
    "free" : 4344,
    "speculative" : 1071
  }
},
  "largestProcess" : "XXXApp",
  "genCounter" : 1,
  "processes" : [
  {
    "uuid" : "213c33d7-a2a9-333e-b1e8-293fa1f3a4ce",
    "states" : [
      "daemon",
      "idle"
    ],
    "age" : 1406544508698,
    "purgeable" : 0,
    "fds" : 25,
    "coalition" : 486,
    "rpages" : 75,
    "priority" : 0,
    "physicalPages" : {
      "internal" : [
        1,
        62
      ]
    },
    ...
  • rpages代表頁的大小,
  • pageSize" : 16384,為當前裝置頁框的大小4KB
  • 通過 rpages * pageSize 就能得出當前app被殺掉時佔用的記憶體
    ## Jetsam機制
    它可以理解為作業系統為了控制記憶體資源過度使用而採用的一種管理機制。Jetsam是一個獨立執行的程序,每一個程序都有一個記憶體閾值,超過這個值的時候,如果手機系統記憶體吃緊就很大機率被系統殺掉.

為什要設計Jetsam機制

大部分的移動裝置都不支援交換空間(虛擬記憶體,將部分實體記憶體交換到磁碟空間上,利用硬碟來擴充套件記憶體空間),而移動端裝置通常採用快閃記憶體儲存,讀寫速度遠小於電腦硬碟,就算使用了交換空間也不一定能夠起到很好的效果,而且移動裝置的容量本省比較小,所以不大適合拿山存來進行記憶體交換。

記憶體一般分為這個幾個狀態

Clean memory, 如frameworks中的__DATA_CONST,如果有新的資料寫入就程式設計dirty
Dirty memory, 被寫入過資料的區域,如_DATA_DATA_DIRTY段,他們是Dirty memory
Compressed Memory 壓縮記憶體,用來替代交換機制,增加記憶體的利用率。 主要正對 不獲取的記憶體壓縮,支援多核操作
在計算記憶體時 壓縮的記憶體也屬於 Dirty memory

Memory Warning

記憶體警告,是系統的一種預警行為,如iOS中的didReceivedMemoryWarning
合理利用快取能提升app的效能,但同時也要避免記憶體的過度開銷,主意清理時機,設定適當的策略進行優化。 比如避按活躍度清理,按大小清理,懶載入,記憶體警告時清理不必要的快取,設定時間策略,將果酒的快取清理等等, 可以考慮使用NSCache代理NSDictionary,NSCache內部實現了一套機制可以在記憶體過高的時候幫助釋放不常用的儲存資料。

OOM的閾值

這個沒有一個明確的值,這個和機型,裝置當前的執行狀態等諸多因數有關,根據我自己的XS的Jetsam的資料來看一般操作500M就有機率出現OOM了,記憶體佔用越高越容易出現OOM

參考

1.https://github.com/Tencent/OOMDetector
2.https://www.taodudu.cc/news/show-5381.html
3.https://juejin.im/post/6885144933997494280