Informazioni sulla gestione della memoria

L'ottimizzazione della memoria è fondamentale per offrire esperienze di gioco stabili e ad alte prestazioni su Android. Questa guida fornisce una panoramica del motivo per cui l'efficienza della memoria è importante, di come il sistema operativo Android gestisce e applica i limiti di memoria dei processi e delle nuove soglie esposte in Google Play Console per aiutarti a monitorare e migliorare la qualità tecnica del tuo gioco.

L'importanza dell'ottimizzazione della memoria

L'ottimizzazione della memoria del gioco è essenziale per mantenere la fidelizzazione dei giocatori, espandere la compatibilità dei dispositivi e rispettare gli standard di qualità della piattaforma:

  • Prevenzione dell'avvio a freddo (esperienza utente e fidelizzazione): quando un giocatore si allontana temporaneamente dal gioco (ad esempio, per rispondere a una notifica o controllare un messaggio), il sistema operativo inserisce il processo del gioco in background. Se il footprint della memoria in background del gioco è troppo elevato, Low Memory Killer (LMK) del sistema assegna la priorità alla terminazione del processo del gioco per recuperare la RAM per le attività in primo piano. La volta successiva che l'utente riprende il gioco, invece di una ripresa a caldo fluida e istantanea, il gioco deve subire un lungo avvio a freddo, ricaricando completamente le risorse grafiche pesanti, l'audio e i file binari del motore di gioco dallo spazio di archiviazione. Mantenere basso l'utilizzo della memoria utilizzata in background impedisce queste terminazioni silenziose in background, preservando lo stato dell'utente e garantendo che i giocatori possano riprendere immediatamente la sessione. Per maggiori dettagli sul comportamento di LMK del sistema, consulta la guida Android Vitals - Low memory killers.
  • Stabilità dell'ecosistema e del dispositivo: l'utilizzo inefficiente della memoria e le perdite di memoria peggiorano la salute generale del sistema. Quando la memoria di sistema è scarsa, il sistema è sottoposto a una forte pressione, con conseguenti cali della frequenza fotogrammi, scatti dell'interfaccia utente e problemi audio. Se la pressione della memoria è troppo elevata, Low Memory Killer (LMK) del sistema termina in modo aggressivo i processi in background, costringendo le altre applicazioni a subire avvii a freddo lenti e a perdere lo stato dell'utente quando i giocatori passano da un'attività all'altra.
  • Terminazioni a livello di piattaforma: a partire da Android 17 (livello API 37), il sistema è più proattivo nella terminazione dei processi che utilizzano troppa memoria. Se il footprint del gioco è troppo elevato, il sistema operativo può terminare il processo in modo improvviso senza generare un'analisi dello stack standard.
  • Compatibilità dei dispositivi: mentre i dispositivi di punta sono dotati di 12-16 GB di RAM, una parte enorme del pubblico di gioco globale utilizza dispositivi con 4 o 6 GB di RAM. Una corretta gestione della memoria garantisce che il gioco rimanga accessibile e reattivo su tutti i livelli hardware senza richiedere pacchetti di asset complessi e separati.

Informazioni sulla memoria in Android

Per progettare strategie efficaci di budget della memoria, gli sviluppatori devono comprendere come la piattaforma Android gestisce la memoria fisica e come misura il footprint attivo del gioco.

Concetti di base della memoria di Android

Per i concetti di base relativi alla gestione della memoria a livello di piattaforma, consulta la documentazione ufficiale Panoramica della gestione della memoria. Questa risorsa tratta quattro aree architettoniche:

  • Panoramica della memoria: Android utilizza il paging e il mapping della memoria (mmap) per gestire la RAM. Non supporta un file di swap tradizionale sul disco, ma si basa sulla compressione delle pagine (utilizzando zRAM) e sul recupero delle pagine per liberare memoria fisica.
  • Allocazione della memoria tra i processi: Android condivide la RAM su tutto il sistema. Assegna heap specifici per l'esecuzione della macchina virtuale Dalvik o ART, consentendo al contempo agli ambienti di sviluppo nativi (come i motori di gioco C++) di richiedere memoria dall'heap di sistema nativo.
  • Gestione della memoria delle app: operando in base a un modello multi-processo, Android si aspetta che le applicazioni monitorino dinamicamente il loro stato del ciclo di vita e rilascino volontariamente le risorse non necessarie (come la grafica e le bitmap non memorizzate nella cache) per supportare la salute del sistema.
  • Panoramica di processi e thread: il sistema classifica i processi in una gerarchia in base alla visibilità e all'importanza percepite dall'utente corrente, determinando quali processi vengono mantenuti attivi e quali vengono terminati per primi in condizioni di memoria insufficiente.

La metrica del footprint totale della memoria

Il limitatore di memoria di Android 17 a livello di piattaforma valuta il consumo dei processi utilizzando il footprint totale della memoria anziché la dimensione residente totale (RSS) o la dimensione della memoria virtuale.

Footprint totale della memoria = RSS anonimo (RssAnon) + Swap non compresso (VmSwap)

Per evitare che i giochi superino i limiti applicati dalla piattaforma, gli sviluppatori devono comprendere esattamente cosa rappresentano queste metriche a livello di sistema. Per ulteriori informazioni su queste metriche, sulle allocazioni di RAM fisica e su come vengono gestite le pagine supportate da file, consulta la sezione Informazioni sulle metriche RSS e Swap nella guida Monitorare l'utilizzo della memoria.

Vincoli di memoria

Per mantenere la stabilità del sistema e garantire che le applicazioni non consumino risorse eccessive, la piattaforma Android applica limiti di memoria ai processi in esecuzione.

Limitatore di memoria in Android 17 e versioni successive

Android 17 e versioni successive applicano limiti di memoria rigorosi per app utilizzando Linux cgroup v2 per impedire che le singole app causino instabilità a livello di sistema. Per maggiori dettagli sull'implementazione tecnica, consulta la guida AOSP Memory Limiter e il post del blog Prioritizing Memory Efficiency: Essential Steps for Android 17.

  • Meccanismo: il limitatore di memoria monitora tutti i processi delle applicazioni e assegna dinamicamente i limiti in base allo stato del ciclo di vita del processo:
    • Processi visibili (in primo piano): i processi delle app che attualmente mostrano un' interfaccia utente dovrebbero eseguire un set di lavoro di risorse più grande e hanno un limite più generoso.
    • Processi non visibili (in background o servizi): i processi delle app che eseguono attività attive senza mostrare un'interfaccia utente sono vincolati a un budget più ristretto e più restrittivo.
  • Attributi del kernel: il servizio si basa su due attributi principali:
    • memory.high: un limite soft. Quando viene superato, il kernel limita il processo e tenta di recuperare la memoria in modo aggressivo. Questo recupero può causare un peggioramento delle prestazioni del gioco.
    • memory.swap.max: applica un limite massimo rigido allo spazio di swap o zRAM che il processo può utilizzare.
  • Comportamento di terminazione: se un processo continua ad allocare memoria anonima oltre memory.high ed esaurisce la capacità di swap, le allocazioni non riescono, e il sistema operativo termina il processo in modo silenzioso. Questa terminazione viene registrata utilizzando ApplicationExitInfo nel motivo di uscita del limitatore di memoria (disponibile a partire da Android 17, 26Q4).

Monitorare l'utilizzo della memoria

Per ottimizzare in modo efficace la memoria del gioco, devi prima comprendere come la piattaforma Android misura il suo footprint. Android 17 aggiorna la metrica di applicazione della memoria per monitorare la somma di RSS anonimo (RssAnon) e Swap non compresso (VmSwap), escludendo la memoria supportata da file o privata della GPU. Questa guida spiega come utilizzare strumenti a livello di sistema come Perfetto e meminfo, implementare API di diagnostica come ProfilingManager e onTrimMemory ed estrarre allocazioni di memoria precise in Unity e Unreal Engine. Scopri come profilare con precisione il gioco ed evitare gli scatti delle prestazioni associati al polling della memoria di runtime tradizionale.

Per saperne di più, consulta Monitorare l'utilizzo della memoria.

Strategie di riduzione della memoria

Sebbene i motori di gioco semplifichino lo sviluppo multipiattaforma, la gestione della memoria predefinita può attivare i limiti di memoria a livello di sistema operativo. Questa pagina descrive i passaggi pratici di ottimizzazione specificamente adattati per Unity e Unreal Engine. Scopri perché l'utilizzo di onTrimMemory basato su Java può causare deadlock in Unity e come utilizzare invece i callback del ciclo di vita nativi. Scoprirai anche le ottimizzazioni chiave a livello di asset, come l'utilizzo della compressione delle texture ASTC 8x8 e la configurazione degli scaricamenti degli asset, per garantire che il gioco funzioni senza problemi su tutti i livelli hardware.