Jitterbedingte Ruckler identifizieren

Jitter ist das zufällige Systemverhalten, das die Ausführung wahrnehmbarer Arbeit verhindert. Auf dieser Seite wird beschrieben, wie du Probleme mit Rucklern, die durch Jitter verursacht werden, identifizieren und beheben kannst.

Verzögerung des App-Thread-Planers

Die Verzögerung des Schedulers ist das offensichtlichste Symptom für Jitter: Ein Prozess, der ausgeführt werden sollte, wird ausführbar gemacht, wird aber für eine beträchtliche Zeit nicht ausgeführt. Die Bedeutung der Verzögerung hängt vom Kontext ab. Beispiel:

  • Ein zufälliger Hilfsthread in einer App kann wahrscheinlich problemlos um viele Millisekunden verzögert werden.
  • Der UI-Thread einer App kann möglicherweise 1–2 ms Jitter tolerieren.
  • Treiber-Kerne, die als SCHED_FIFO ausgeführt werden, können Probleme verursachen, wenn sie 500 µs lang ausführbar sind, bevor sie ausgeführt werden.

Ausführbare Zeiten sind in systrace an der blauen Leiste zu erkennen, die einem laufenden Segment eines Threads vorangestellt ist. Eine ausführbare Zeit kann auch durch die Zeitspanne zwischen dem sched_wakeup-Ereignis für einen Thread und dem sched_switch-Ereignis bestimmt werden, das den Beginn der Threadausführung signalisiert.

Threads, die zu lange laufen

Threads der App-Benutzeroberfläche, die zu lange ausgeführt werden, können zu Problemen führen. Threads niedrigerer Ebene mit langen Laufzeiten haben in der Regel andere Ursachen. Wenn Sie jedoch versuchen, die Laufzeit des UI-Threads auf null zu senken, müssen möglicherweise einige der Probleme behoben werden, die zu langen Laufzeiten von Threads niedrigerer Ebene führen. So vermeiden Sie Verzögerungen:

  1. Verwenden Sie cpusets wie unter Thermisches Throttling beschrieben.
  2. Erhöhen Sie den Wert von CONFIG_HZ.
    • Bisher wurde der Wert auf arm- und arm64-Plattformen auf 100 festgelegt. Dies ist jedoch ein historischer Zufall und kein geeigneter Wert für interaktive Geräte. CONFIG_HZ=100 bedeutet, dass ein Jiffy 10 ms lang ist. Das bedeutet, dass der Lastenausgleich zwischen den CPUs 20 ms (zwei Jiffys) dauern kann. Dies kann zu Rucklern bei einem ausgelasteten System führen.
    • Neuere Geräte (Nexus 5X, Nexus 6P, Pixel und Pixel XL) wurden mit der Einstellung CONFIG_HZ=300 ausgeliefert. Dies sollte nur unerhebliche Energiekosten verursachen und gleichzeitig die Laufzeiten deutlich verbessern. Wenn Sie nach der Änderung von CONFIG_HZ einen deutlichen Anstieg des Stromverbrauchs oder Leistungsprobleme feststellen, verwendet einer Ihrer Treiber wahrscheinlich einen Timer, der auf Roh-Jiffys anstelle von Millisekunden basiert und in Jiffys konvertiert. Das Problem lässt sich in der Regel leicht beheben (siehe Patch, mit dem Probleme mit dem kgsl-Timer auf Nexus 5X und 6P bei der Umstellung auf CONFIG_HZ=300 behoben wurden).
    • Schließlich haben wir mit CONFIG_HZ=1000 auf Nexus/Pixel experimentiert und festgestellt, dass dies aufgrund des reduzierten RCU-Overheads eine deutliche Leistungs- und Energieeinsparung bietet.

Allein durch diese beiden Änderungen sollte sich die ausführbare Zeit des UI-Threads unter Last auf einem Gerät deutlich verbessern.

sys.use_fifo_ui verwenden

Sie können versuchen, die ausführbare Zeit des UI-Threads auf null zu setzen, indem Sie das Attribut sys.use_fifo_ui auf „1“ festlegen.

Warnung: Verwenden Sie diese Option nicht für heterogene CPU-Konfigurationen, es sei denn, Sie haben einen kapazitätsbewussten RT-Planer. Derzeit ist KEIN AKTUELL VERSENDETER RT-PLANER KAPAZITÄTSBEWUSST. Wir arbeiten an einer Lösung für EAS, die aber noch nicht verfügbar ist. Der Standard-RT-Scheduler basiert ausschließlich auf RT-Prioritäten und darauf, ob eine CPU bereits einen RT-Thread mit gleicher oder höherer Priorität hat.

Daher verschiebt der Standard-RT-Scheduler Ihren relativ lang laufenden UI-Thread gerne von einem Big-Core mit hoher Taktfrequenz zu einem Little-Core mit minimaler Taktfrequenz, wenn ein FIFO-Kthread mit höherer Priorität auf demselben Big-Core wieder aktiv wird. Das führt zu erheblichen Leistungseinbußen. Da diese Option noch nicht auf einem Android-Gerät verwendet wurde, wenden Sie sich an das Android-Leistungsteam, wenn Sie sie verwenden möchten.

Wenn sys.use_fifo_ui aktiviert ist, überwacht ActivityManager den UI-Thread und den RenderThread (die beiden für die Benutzeroberfläche wichtigsten Threads) der führenden App und weist diesen Threads SCHED_FIFO anstelle von SCHED_OTHER zu. Dadurch wird Jitter von UI- und Render-Threads effektiv eliminiert. Die mit dieser Option erfassten Traces zeigen ausführbare Zeiten in der Größenordnung von Mikrosekunden anstelle von Millisekunden.

Da der RT-Load Balancer jedoch nicht kapazitätsabhängig war, ging die Leistung beim Starten der App um 30% zurück, da der für das Starten der App zuständige UI-Thread von einem 2,1-GHz-Gold-Kryo-Kern auf einen 1,5-GHz-Silber-Kryo-Kern verschoben wurde. Mit einem kapazitätsbewussten RT-Load Balancer erzielen wir bei Bulk-Vorgängen eine vergleichbare Leistung und eine Reduzierung der Frame-Zeiten beim 95. und 99. Perzentil um 10–15% in vielen unserer UI-Benchmarks.

Traffic unterbrechen

Da ARM-Plattformen standardmäßig nur an CPU 0 Interrupts senden, empfehlen wir die Verwendung eines IRQ-Balancers (irqbalance oder msm_irqbalance auf Qualcomm-Plattformen).

Während der Entwicklung von Pixel haben wir Ruckler festgestellt, die direkt auf eine Überlastung der CPU 0 durch Unterbrechungen zurückzuführen waren. Wenn der mdss_fb0-Thread beispielsweise auf CPU 0 geplant wurde, war die Wahrscheinlichkeit von Rucklern aufgrund eines Interrupts, der vom Display fast unmittelbar vor dem Auslesen ausgelöst wird, viel höher. mdss_fb0 wäre mitten in seiner eigenen Arbeit mit einem sehr engen Termin und würde dann etwas Zeit durch den MDSS-Unterbrechungshandler verlieren. Wir haben versucht, das Problem zu beheben, indem wir die CPU-Affinität des mdss_fb0-Threads auf die CPUs 1–3 gesetzt haben, um Konflikte mit dem Interrupt zu vermeiden. Wir haben dann aber festgestellt, dass wir msm_irqbalance noch nicht aktiviert hatten. Wenn msm_irqbalance aktiviert ist, wurde das Ruckeln aufgrund von weniger Konflikten durch andere Unterbrechungen deutlich verbessert, selbst wenn sich sowohl mdss_fb0 als auch der MDSS-Unterbrechung auf derselben CPU befanden.

Dies kann in systrace im Abschnitt „sched“ und im Abschnitt „irq“ ermittelt werden. Im Abschnitt „sched“ wird angezeigt, was geplant wurde. Ein sich überschneidender Bereich im Abschnitt „irq“ bedeutet jedoch, dass zu diesem Zeitpunkt ein Interrupt ausgeführt wird, anstatt des normalerweise geplanten Prozesses. Wenn Sie sehen, dass bei einer Unterbrechung viel Zeit in Anspruch genommen wird, haben Sie folgende Möglichkeiten:

  • Den Interrupt-Handler schneller machen.
  • Unterbrechungen vermeiden
  • Ändern Sie die Häufigkeit der Unterbrechung, damit sie nicht mit anderen regelmäßigen Aufgaben übereinstimmt, die sie möglicherweise beeinträchtigt (falls es sich um eine regelmäßige Unterbrechung handelt).
  • Legen Sie die CPU-Affinität des Interrupts direkt fest und verhindern Sie, dass er ausgeglichen wird.
  • Legen Sie die CPU-Affinität des Threads fest, der durch den Interrupt unterbrochen wird, um den Interrupt zu vermeiden.
  • Der Interrupt-Balancer verschiebt den Interrupt auf eine weniger ausgelastete CPU.

Das Festlegen der CPU-Affinität wird im Allgemeinen nicht empfohlen, kann aber in bestimmten Fällen nützlich sein. Im Allgemeinen ist es zu schwierig, den Zustand des Systems für die meisten gängigen Unterbrechungen vorherzusagen. Wenn jedoch sehr spezifische Bedingungen bestimmte Unterbrechungen auslösen, bei denen das System stärker eingeschränkt ist als normal (z. B. bei VR), kann eine explizite CPU-Affinität eine gute Lösung sein.

Lange Soft-IRQs

Während ein Soft-IRQ ausgeführt wird, wird die Voraktivierung deaktiviert. Soft-IRQs können auch an vielen Stellen im Kernel ausgelöst und innerhalb eines Nutzerprozesses ausgeführt werden. Bei ausreichender Softirq-Aktivität beenden Nutzerprozesse die Ausführung von Softirqs und ksoftirqd wird gestartet, um Softirqs auszuführen und die Auslastung auszugleichen. Das ist in der Regel kein Problem. Ein einzelner sehr langer Softirq kann jedoch das System beeinträchtigen.


Softirqs sind im IRQ-Abschnitt eines Tracings sichtbar. Sie können also leicht erkannt werden, wenn das Problem während des Tracings reproduziert werden kann. Da ein Soft-IRQ innerhalb eines Nutzerprozesses ausgeführt werden kann, kann sich ein fehlerhafter Soft-IRQ auch ohne offensichtlichen Grund als zusätzliche Laufzeit innerhalb eines Nutzerprozesses manifestieren. Prüfen Sie in diesem Fall im Abschnitt „irq“, ob Soft-IRQs die Ursache sind.

Treiber, die die Voraktivierung oder IRQs zu lange deaktivieren

Wenn Sie die Voraktivierung oder Unterbrechungen zu lange (mehrere zehn Millisekunden) deaktivieren, kommt es zu Rucklern. Normalerweise äußert sich das Ruckeln darin, dass ein Thread ausführbar wird, aber nicht auf einer bestimmten CPU ausgeführt wird, auch wenn der ausführbare Thread eine deutlich höhere Priorität (oder SCHED_FIFO) als der andere Thread hat.

Einige Richtlinien:

  • Wenn der ausführbare Thread SCHED_FIFO und der laufende Thread SCHED_OTHER ist, sind Voremption oder Unterbrechungen für den laufenden Thread deaktiviert.
  • Wenn der ausführbare Thread eine deutlich höhere Priorität (100) als der laufende Thread (120) hat, sind bei letzterem wahrscheinlich Voremption oder Unterbrechungen deaktiviert, wenn der ausführbare Thread nicht innerhalb von zwei Jiffys ausgeführt wird.
  • Wenn der ausführbare Thread und der laufende Thread dieselbe Priorität haben, sind für den laufenden Thread wahrscheinlich Voremption oder Unterbrechungen deaktiviert, wenn der ausführbare Thread nicht innerhalb von 20 ms ausgeführt wird.

Beachten Sie, dass durch das Ausführen eines Interrupt-Handlers die Verarbeitung anderer Interrupts verhindert wird. Außerdem wird die Voraktivierung deaktiviert.


Eine weitere Möglichkeit zur Identifizierung von betroffenen Regionen ist der Tracer preemptirqsoff (siehe Dynamische ftrace verwenden). Dieser Tracer kann viel mehr Aufschluss über die Ursache einer nicht unterbrechbaren Region geben (z. B. Funktionsnamen), erfordert aber mehr Aufwand bei der Aktivierung. Das kann zwar Auswirkungen auf die Leistung haben, ist aber auf jeden Fall einen Versuch wert.

Falsche Verwendung von Arbeitswarteschlangen

Unterbrechungsabarbeiter müssen oft Aufgaben ausführen, die außerhalb eines Unterbrechungskontexts ausgeführt werden können. So können Aufgaben an verschiedene Threads im Kernel vergeben werden. Ein Treiberentwickler stellt möglicherweise fest, dass der Kernel eine sehr praktische systemweite asynchrone Aufgabenfunktion namens workqueues hat, und verwendet diese für unterbrechungsbezogene Aufgaben.

Workqueues sind jedoch fast immer die falsche Antwort auf dieses Problem, da sie immer SCHED_OTHER sind. Viele Hardwareunterbrechungen befinden sich auf dem kritischen Pfad der Leistung und müssen sofort ausgeführt werden. Bei Arbeitswarteschlangen kann nicht garantiert werden, wann sie ausgeführt werden. Jedes Mal, wenn wir einen Arbeitsvorgang im kritischen Pfad der Leistung gesehen haben, war dies unabhängig vom Gerät eine Quelle für sporadisch auftretende Ruckler. Auf Pixel mit einem Flagship-Prozessor haben wir festgestellt, dass eine einzelne Arbeitswarteschlange bei hoher Auslastung des Geräts je nach Scheduler-Verhalten und anderen Systemaktivitäten bis zu 7 ms verzögert werden kann.

Anstelle eines Arbeitsqueues sollten Treiber, die unterbrechungsähnliche Aufgaben in einem separaten Thread bearbeiten müssen, ihren eigenen SCHED_FIFO-Kthread erstellen. Weitere Informationen dazu, wie Sie dies mit kthread_work-Funktionen tun, finden Sie in diesem Patch.

Framework-Sperre – Konflikt

Konflikte bei der Framework-Sperre können zu Rucklern oder anderen Leistungsproblemen führen. In der Regel wird sie durch die Sperre des ActivityManagerService verursacht, kann aber auch bei anderen Sperren auftreten. So kann sich die Sperre des PowerManagerService beispielsweise auf die Leistung des Displays auswirken. Wenn du diese Meldung auf deinem Gerät siehst, gibt es keine gute Lösung, da das Problem nur durch architektonische Verbesserungen am Framework behoben werden kann. Wenn Sie jedoch Code ändern, der im system_server ausgeführt wird, sollten Sie unbedingt vermeiden, Sperren für längere Zeit zu halten, insbesondere die Sperre für den ActivityManagerService.

Binder Lock Contention

Bisher gab es bei Binder nur eine einzige globale Sperre. Wenn der Thread, der eine Binder-Transaktion ausführt, während der Sperrung vorzeitig beendet wurde, kann kein anderer Thread eine Binder-Transaktion ausführen, bis der ursprüngliche Thread die Sperre aufgehoben hat. Das ist schlecht. Binderkonflikte können alles im System blockieren, einschließlich des Sendens von UI-Aktualisierungen an das Display (UI-Threads kommunizieren über Binder mit SurfaceFlinger).

Android 6.0 enthält mehrere Patches, um dieses Verhalten zu verbessern. Dabei wird die Voraktivierung deaktiviert, während die Bindersperre gehalten wird. Dies war nur sicher, weil die Bindersperre für einige Mikrosekunden der tatsächlichen Laufzeit gehalten werden sollte. Dadurch wurde die Leistung in Situationen ohne Konflikte deutlich verbessert und Konflikte verhindert, da die meisten Scheduler-Wechsel verhindert wurden, während die Bindersperre gehalten wurde. Die Voraktivierung konnte jedoch nicht für die gesamte Laufzeit der Bindersperre deaktiviert werden. Das bedeutet, dass die Voraktivierung für Funktionen aktiviert war, die in den Ruhemodus versetzt werden können (z. B. copy_from_user). Dies könnte zu derselben Voraktivierung wie im ursprünglichen Fall führen. Als wir die Patches weitergeleitet haben, wurde uns sofort mitgeteilt, dass dies die schlechteste Idee der Welt sei. Wir stimmten ihnen zu, konnten aber auch nicht gegen die Wirksamkeit der Patches zur Vermeidung von Rucklern argumentieren.

fd-Konflikte innerhalb eines Prozesses

Das kommt selten vor. Das Problem wird wahrscheinlich nicht dadurch verursacht.

Wenn jedoch mehrere Threads innerhalb eines Prozesses auf dasselbe Dateiobjekt schreiben, kann es zu Konflikten kommen. Wir haben dieses Problem jedoch nur bei einem Test festgestellt, bei dem Threads mit niedriger Priorität versuchten, die gesamte CPU-Zeit zu belegen, während ein einzelner Thread mit hoher Priorität im selben Prozess ausgeführt wurde. Alle Threads haben auf den Dateideskriptor der Trace-Markierung geschrieben und der Thread mit hoher Priorität konnte am Dateideskriptor der Trace-Markierung blockiert werden, wenn ein Thread mit niedriger Priorität die fd-Sperre hielt und dann vorzeitig beendet wurde. Nachdem die Threads mit niedriger Priorität nicht mehr getrackt wurden, trat das Leistungsproblem nicht mehr auf.

Wir konnten das Problem in keiner anderen Situation reproduzieren, es ist aber eine mögliche Ursache für Leistungsprobleme beim Tracen.

Unnötige CPU-Leerlaufübergänge

Beim Umgang mit IPC, insbesondere bei Pipelines mit mehreren Prozessen, treten häufig Abweichungen vom folgenden Laufzeitverhalten auf:

  1. Thread A wird auf CPU 1 ausgeführt.
  2. Thread A weckt Thread B auf.
  3. Thread B wird auf CPU 2 ausgeführt.
  4. Thread A wird sofort in den Ruhemodus versetzt und von Thread B wieder geweckt, wenn Thread B seine aktuelle Arbeit beendet hat.

Eine häufige Quelle für Overhead liegt zwischen Schritt 2 und 3. Wenn CPU 2 inaktiv ist, muss sie in einen aktiven Zustand versetzt werden, bevor Thread B ausgeführt werden kann. Je nach SOC und Auslastung kann es zehn Mikrosekunden dauern, bis Thread B ausgeführt wird. Wenn die tatsächliche Laufzeit jeder Seite der IPC dem Overhead nahekommt, kann die Gesamtleistung dieser Pipeline durch CPU-Ruhezustände erheblich reduziert werden. Am häufigsten tritt dieses Problem bei Android bei Binder-Transaktionen auf. Viele Dienste, die Binder verwenden, sehen dann so aus wie oben beschrieben.

Verwenden Sie zuerst die Funktion wake_up_interruptible_sync() in Ihren Kerneltreibern und unterstützen Sie diese Funktion über einen beliebigen benutzerdefinierten Scheduler. Dies ist keine Empfehlung, sondern eine Anforderung. Binder verwendet diese Funktion bereits und sie hilft bei synchronen Binder-Transaktionen, unnötige CPU-Ruhezustände zu vermeiden.

Zweitens: Achten Sie darauf, dass die cpuidle-Übergangszeiten realistisch sind und vom cpuidle-Governor korrekt berücksichtigt werden. Wenn der SOC zwischen dem tiefsten Inaktivitätsstatus hin- und herwechselt, sparen Sie nicht durch den tiefsten Inaktivitätsstatus Strom.

Protokollierung

Das Logging beansprucht CPU-Zyklen und Arbeitsspeicher. Überlasten Sie den Protokoll-Puffer daher nicht. Die Protokollierungskosten werden direkt in Ihrer App und im Log-Daemon berechnet. Entfernen Sie alle Protokolle zur Fehlerbehebung, bevor Sie das Gerät versenden.

E/A-Probleme

E/A-Vorgänge sind häufige Ursachen für Jitter. Wenn ein Thread auf eine speicherabgebildete Datei zugreift und die Seite nicht im Seitencache ist, wird ein Fehler ausgegeben und die Seite vom Laufwerk gelesen. Dadurch wird der Thread blockiert (in der Regel für mehr als 10 ms). Wenn dies auf dem kritischen Pfad des UI-Renderings geschieht, kann es zu Rucklern kommen. Es gibt zu viele Ursachen für I/O-Vorgänge, um sie hier zu erwähnen. Prüfen Sie jedoch die folgenden Bereiche, wenn Sie das I/O-Verhalten verbessern möchten:

  • PinnerService PinnerService wurde in Android 7.0 hinzugefügt und ermöglicht es dem Framework, einige Dateien im Seitencache zu sperren. Dadurch wird der Speicher für die Verwendung durch andere Prozesse entfernt. Wenn jedoch einige Dateien bekannt sind, die regelmäßig verwendet werden, kann es effektiv sein, diese Dateien zu mlocken.

    Auf Pixel- und Nexus 6P-Geräten mit Android 7.0 wurden vier Dateien gesperrt:
    • /system/framework/arm64/boot-framework.oat
    • /system/framework/oat/arm64/services.odex
    • /system/framework/arm64/boot.oat
    • /system/framework/arm64/boot-core-libart.oat
    Diese Dateien werden von den meisten Apps und dem system_server ständig verwendet und sollten daher nicht ausgelagert werden. Insbesondere haben wir festgestellt, dass diese Elemente, wenn sie ausgelagert werden, wiederhergestellt werden und beim Wechsel von einer ressourcenintensiven App zu Rucklern führen.
  • Verschlüsselung Eine weitere mögliche Ursache für I/O-Probleme. Wir haben festgestellt, dass die Inline-Verschlüsselung im Vergleich zur CPU-basierten Verschlüsselung oder der Verwendung eines über DMA zugänglichen Hardwareblocks die beste Leistung bietet. Vor allem reduziert die Inline-Verschlüsselung den Jitter bei E/A, insbesondere im Vergleich zur CPU-basierten Verschlüsselung. Da Abrufe im Seitencache oft auf dem kritischen Pfad des UI-Renderings liegen, führt die CPU-basierte Verschlüsselung zu einer zusätzlichen CPU-Auslastung auf dem kritischen Pfad, was zu mehr Jitter als nur beim I/O-Abruf führt.

    DMA-basierte Hardware-Verschlüsselungs-Engines haben ein ähnliches Problem, da der Kernel Zyklen für die Verwaltung dieser Arbeit aufwenden muss, auch wenn andere kritische Aufgaben ausgeführt werden können. Wir empfehlen allen Anbietern von Sicherheitslösungen, die neue Hardware entwickeln, die Unterstützung für die Inline-Verschlüsselung zu implementieren.

Aggressives Packen kleiner Aufgaben

Einige Scheduler unterstützen das Packen kleiner Aufgaben auf einzelne CPU-Kerne, um den Stromverbrauch zu senken, indem mehr CPUs länger inaktiv bleiben. Das funktioniert zwar gut für Durchsatz und Energieverbrauch, kann aber katastrophale Auswirkungen auf die Latenz haben. Es gibt mehrere kurz laufende Threads im kritischen Pfad des UI-Renderings, die als klein betrachtet werden können. Wenn diese Threads verzögert werden, da sie langsam auf andere CPUs migriert werden, führt dies zu Rucklern. Wir empfehlen, die Gruppierung kleiner Aufgaben sehr konservativ zu verwenden.

Auslastung des Seitencaches

Ein Gerät ohne ausreichend kostenlosen Arbeitsspeicher kann bei einem langwierigen Vorgang wie dem Öffnen einer neuen App plötzlich extrem langsam werden. Ein App-Trace kann zeigen, dass die App bei einem bestimmten Lauf immer wieder bei E/A-Vorgängen blockiert wird, auch wenn dies bei E/A-Vorgängen häufig nicht der Fall ist. Dies ist in der Regel ein Zeichen für einen Page-Cache-Trashing, insbesondere auf Geräten mit weniger Arbeitsspeicher.

Eine Möglichkeit, dies zu ermitteln, besteht darin, einen Systrace mit dem Tag „pagecache“ zu erstellen und diesen Trace an das Script unter system/extras/pagecache/pagecache.py zu übergeben. pagecache.py übersetzt einzelne Anfragen zum Zuordnen von Dateien in den Seitencache in aggregierte Statistiken pro Datei. Wenn mehr Byte einer Datei gelesen wurden als die Gesamtgröße dieser Datei auf dem Laufwerk, ist der Auslagerungs-Cache definitiv überlastet.

Das bedeutet, dass der Arbeitssatz, der für Ihre Arbeitslast erforderlich ist (in der Regel eine einzelne App plus system_server), größer ist als der Arbeitsspeicher, der für den Auslagerungsbereich auf Ihrem Gerät verfügbar ist. Wenn also ein Teil der Arbeitslast die benötigten Daten im Seitencache abruft, wird ein anderer Teil, der in naher Zukunft verwendet wird, entfernt und muss noch einmal abgerufen werden. Das Problem tritt so lange auf, bis die Ladung abgeschlossen ist. Das ist die Hauptursache für Leistungsprobleme, wenn auf einem Gerät nicht genügend Arbeitsspeicher verfügbar ist.

Es gibt keine hundertprozentig zuverlässige Methode, um das Überschreiben des Seitencaches zu beheben. Es gibt jedoch einige Möglichkeiten, dies auf einem bestimmten Gerät zu verbessern.

  • Weniger Arbeitsspeicher in persistenten Prozessen verwenden Je weniger Arbeitsspeicher von persistenten Prozessen verwendet wird, desto mehr Arbeitsspeicher steht Apps und dem Auslagerungscache zur Verfügung.
  • Prüfen Sie die Auslagerungen für Ihr Gerät, um sicherzustellen, dass Sie nicht unnötig Speicherplatz vom Betriebssystem entfernen. Es gab Fälle, in denen für das Debugging verwendete Aussparungen versehentlich in den ausgelieferten Kernelkonfigurationen verblieben und dadurch Zehntausende von Megabyte an Speicher belegt wurden. Dies kann den Unterschied ausmachen, ob es zu einem Ausschlag des Seitencaches kommt oder nicht, insbesondere auf Geräten mit weniger Arbeitsspeicher.
  • Wenn Sie im system_server bei kritischen Dateien einen Auslagerungs-Cache-Trashing feststellen, sollten Sie diese Dateien anpinnen. Dadurch wird der Arbeitsspeicherdruck an anderer Stelle erhöht, aber das Verhalten kann so verändert werden, dass ein Überlastungszustand vermieden wird.
  • Passen Sie lowmemorykiller an, um mehr Arbeitsspeicher freizuhalten. Die Grenzwerte von lowmemorykiller basieren sowohl auf dem absoluten kostenlosen Arbeitsspeicher als auch auf dem Auslagerungs-Cache. Wenn Sie den Grenzwert erhöhen, bei dem Prozesse auf einer bestimmten oom_adj-Ebene beendet werden, kann dies zu einem besseren Verhalten führen, aber zu mehr beendeten Hintergrund-Apps.
  • Versuchen Sie es mit ZRAM. Wir verwenden ZRAM auf Pixel, obwohl Pixel 4 GB RAM hat, da es bei selten verwendeten schmutzigen Seiten helfen kann.