mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-29 23:38:50 +02:00
perf(memory): release Go heap and decoded image caches on OS memory pressure
This commit is contained in:
@@ -3043,6 +3043,12 @@ class MainActivity: FlutterFragmentActivity() {
|
||||
}
|
||||
result.success(null)
|
||||
}
|
||||
"releaseMemory" -> {
|
||||
withContext(Dispatchers.IO) {
|
||||
Gobackend.releaseMemory()
|
||||
}
|
||||
result.success(null)
|
||||
}
|
||||
"getLogCount" -> {
|
||||
val count = withContext(Dispatchers.IO) {
|
||||
Gobackend.getLogCount()
|
||||
|
||||
@@ -2,9 +2,19 @@ package gobackend
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ReleaseMemory drops idle pooled extension runtimes, forces a GC, and
|
||||
// returns freed heap to the OS. Called from the app on OS memory pressure and
|
||||
// when backgrounded, so the Go side's RSS doesn't sit at its high-water mark
|
||||
// after large downloads/tag writes.
|
||||
func ReleaseMemory() {
|
||||
drainAllIsolatedRuntimePools()
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
|
||||
func CheckAvailability(spotifyID, isrc string) (string, error) {
|
||||
client := NewSongLinkClient()
|
||||
availability, err := client.CheckTrackAvailability(spotifyID, isrc)
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:spotiflac_android/providers/library_collections_provider.dart';
|
||||
import 'package:spotiflac_android/providers/local_library_provider.dart';
|
||||
import 'package:spotiflac_android/providers/settings_provider.dart';
|
||||
import 'package:spotiflac_android/services/notification_service.dart';
|
||||
import 'package:spotiflac_android/services/platform_bridge.dart';
|
||||
import 'package:spotiflac_android/services/share_intent_service.dart';
|
||||
import 'package:spotiflac_android/services/cover_cache_manager.dart';
|
||||
import 'package:spotiflac_android/utils/local_library_scan_prefs.dart';
|
||||
@@ -157,9 +158,25 @@ class _EagerInitializationState extends ConsumerState<_EagerInitialization>
|
||||
ref.read(downloadQueueProvider.notifier).flushQueuePersistence(),
|
||||
);
|
||||
}
|
||||
// Backgrounded: return the Go heap's high-water mark to the OS so the
|
||||
// process is a smaller kill target.
|
||||
unawaited(PlatformBridge.releaseNativeMemory());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didHaveMemoryPressure() {
|
||||
// OS memory pressure: drop decoded bitmaps (disk caches stay intact) and
|
||||
// have the Go side release freed heap back to the OS.
|
||||
final imageCache = PaintingBinding.instance.imageCache;
|
||||
imageCache.clear();
|
||||
imageCache.clearLiveImages();
|
||||
if (CoverCacheManager.isInitialized) {
|
||||
CoverCacheManager.instance.store.emptyMemoryCache();
|
||||
}
|
||||
unawaited(PlatformBridge.releaseNativeMemory());
|
||||
}
|
||||
|
||||
void _initializeDeferredProviders() {
|
||||
_downloadHistoryWarmupTimer = _scheduleProviderWarmup(
|
||||
const Duration(milliseconds: 400),
|
||||
|
||||
@@ -1202,6 +1202,14 @@ class PlatformBridge {
|
||||
await _channel.invokeMethod('clearLogs');
|
||||
}
|
||||
|
||||
/// Ask the Go backend to GC and return freed heap to the OS. Best-effort:
|
||||
/// safe to call on memory pressure or when the app is backgrounded.
|
||||
static Future<void> releaseNativeMemory() async {
|
||||
try {
|
||||
await _channel.invokeMethod('releaseMemory');
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
static Future<int> getGoLogCount() async {
|
||||
final result = await _channel.invokeMethod('getLogCount');
|
||||
return result as int;
|
||||
|
||||
Reference in New Issue
Block a user