mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-11 16:57:39 +00:00
feat: scale LocalCache pruning aggressiveness to OS memory-pressure level
MemoryTrimmingService.doTrim() previously ran the full pruning suite regardless of how severe the OS signal was. Now it tiers the work by ComponentCallbacks2 level so low-pressure signals don't pay the cost of aggressive observer teardown: Tier 1 (always): cleanMemory + pruneExpiredEvents + prunePastVersionsOfReplaceables Tier 2 (>= RUNNING_LOW): + pruneOldMessages + pruneRepliesAndReactions Tier 3 (>= RUNNING_CRITICAL): + cleanObservers + pruneHiddenEvents/Messages The `level` is now threaded from Amethyst.onTrimMemory → AppModules.trim(level) → MemoryTrimmingService.run(…, level) → doTrim(…, level). The existing scheduled-trim call site (AppModules.trim) defaults to RUNNING_CRITICAL so its behaviour is unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -852,12 +852,12 @@ class AppModules(
|
||||
accountsCache.clear()
|
||||
}
|
||||
|
||||
fun trim() {
|
||||
fun trim(level: Int) {
|
||||
applicationIOScope.launch {
|
||||
// Backgrounding is a natural moment to flush the DNS cache.
|
||||
dnsStore.save()
|
||||
val loggedIn = accountsCache.accounts.value.values
|
||||
trimmingService.run(loggedIn, LocalPreferences.allSavedAccounts())
|
||||
trimmingService.run(loggedIn, LocalPreferences.allSavedAccounts(), level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
-11
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.service.eventCache
|
||||
|
||||
import android.content.ComponentCallbacks2
|
||||
import com.vitorpamplona.amethyst.AccountInfo
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
@@ -32,33 +33,57 @@ class MemoryTrimmingService(
|
||||
) {
|
||||
var isTrimmingMemoryMutex = AtomicBoolean(false)
|
||||
|
||||
/**
|
||||
* Tiered pruning scaled to the OS memory-pressure level.
|
||||
*
|
||||
* Tier 1 — mild pressure (UI hidden, running-moderate):
|
||||
* Sweep stale WeakRefs, drop expired and superseded-replaceable events.
|
||||
* Safe to run frequently; no UI-visible side effects.
|
||||
*
|
||||
* Tier 2 — low memory (running-low, background):
|
||||
* Tier 1 + old chat messages + unobserved thread replies / reactions.
|
||||
* May cause feeds to re-fetch content that was scrolled past.
|
||||
*
|
||||
* Tier 3 — critical / imminent kill (running-critical, moderate, complete):
|
||||
* Tier 2 + sever all observer links + drop every event from muted/blocked users.
|
||||
* Aggressive; triggers recomposition wherever StateFlows were cleared.
|
||||
*/
|
||||
private fun doTrim(
|
||||
account: Collection<Account>,
|
||||
otherAccounts: List<AccountInfo>,
|
||||
level: Int,
|
||||
) {
|
||||
// Tier 1: always run — cheap housekeeping
|
||||
cache.cleanMemory()
|
||||
cache.cleanObservers()
|
||||
cache.pruneExpiredEvents()
|
||||
cache.prunePastVersionsOfReplaceables()
|
||||
|
||||
account.forEach {
|
||||
cache.pruneHiddenEvents(it)
|
||||
cache.pruneHiddenMessages(it)
|
||||
if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW) {
|
||||
// Tier 2: medium pressure — drop messages and unobserved reactions
|
||||
val accounts = otherAccounts.mapNotNull { decodePublicKeyAsHexOrNull(it.npub) }.toSet()
|
||||
cache.pruneOldMessages()
|
||||
cache.pruneRepliesAndReactions(accounts)
|
||||
}
|
||||
|
||||
val accounts = otherAccounts.mapNotNull { decodePublicKeyAsHexOrNull(it.npub) }.toSet()
|
||||
cache.pruneOldMessages()
|
||||
cache.pruneRepliesAndReactions(accounts)
|
||||
cache.prunePastVersionsOfReplaceables()
|
||||
cache.pruneExpiredEvents()
|
||||
if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) {
|
||||
// Tier 3: critical pressure — sever observer links and drop muted content
|
||||
cache.cleanObservers()
|
||||
account.forEach {
|
||||
cache.pruneHiddenEvents(it)
|
||||
cache.pruneHiddenMessages(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun run(
|
||||
account: Collection<Account>,
|
||||
otherAccounts: List<AccountInfo>,
|
||||
level: Int = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL,
|
||||
) {
|
||||
if (isTrimmingMemoryMutex.compareAndSet(false, true)) {
|
||||
Log.d("ServiceManager", "Trimming Memory")
|
||||
Log.d("ServiceManager", "Trimming Memory (level=$level)")
|
||||
try {
|
||||
doTrim(account, otherAccounts)
|
||||
doTrim(account, otherAccounts, level)
|
||||
} finally {
|
||||
isTrimmingMemoryMutex.getAndSet(false)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user