performance improvements

This commit is contained in:
Fabian Freund
2026-07-31 05:14:27 +02:00
parent c2c7cc0729
commit bdfc851681
36 changed files with 1988 additions and 608 deletions
@@ -33,7 +33,20 @@ part 'singbox_proxy_logs.g.dart';
/// is well within budget for a debugging surface.
const int _ringBufferCapacity = 2000;
/// Lower bound between two published snapshots. A chatty proxy can emit lines
/// far faster than the screen can render them, and every publication copies the
/// whole ring buffer, so coalescing bursts is free in terms of what the user
/// actually sees.
const _publishInterval = Duration(milliseconds: 100);
/// Snapshot of buffered log entries. Most-recent-last (chronological).
///
/// This notifier is `keepAlive` and subscribed from app start (see
/// `main.dart`) so startup messages are retained even before any UI mounts.
/// Appending and *publishing* are therefore deliberately decoupled: lines
/// always land in [_buffer], but a new immutable snapshot is only produced
/// while the log screen is on screen ([setLivePublishing]) and at most once
/// per [_publishInterval].
@Riverpod(keepAlive: true)
class SingboxProxyLogs extends _$SingboxProxyLogs {
final _buffer = Queue<ProxyLogMessage>();
@@ -41,6 +54,28 @@ class SingboxProxyLogs extends _$SingboxProxyLogs {
StreamSubscription<SingboxProxyLogMessage>? _singboxSubscription;
StreamSubscription<TorLogMessage>? _torSubscription;
Timer? _publishTimer;
bool _livePublishing = false;
/// Buffer contents materialized on demand, regardless of publication state.
/// Lets a freshly mounted screen paint the backlog without waiting for the
/// first throttled snapshot.
List<ProxyLogMessage> get snapshot => List.unmodifiable(_buffer);
/// Enables/disables snapshot publication. Called by the log screen as it
/// mounts and unmounts; flushes on both edges so the state left behind is
/// always complete.
void setLivePublishing(bool enabled) {
if (_livePublishing == enabled) {
return;
}
_livePublishing = enabled;
_publishTimer?.cancel();
_publishTimer = null;
_publish();
}
void _append(ProxyLogMessage message) {
_buffer.add(message);
@@ -48,11 +83,27 @@ class SingboxProxyLogs extends _$SingboxProxyLogs {
_buffer.removeFirst();
}
state = List.unmodifiable(_buffer);
if (!_livePublishing || (_publishTimer?.isActive ?? false)) {
return;
}
_publishTimer = Timer(_publishInterval, _publish);
}
void _publish() {
_publishTimer = null;
if (!ref.mounted) {
return;
}
state = snapshot;
}
void clear() {
_buffer.clear();
_publishTimer?.cancel();
_publishTimer = null;
state = const [];
}
@@ -69,10 +120,11 @@ class SingboxProxyLogs extends _$SingboxProxyLogs {
);
ref.onDispose(() {
_publishTimer?.cancel();
unawaited(_singboxSubscription?.cancel());
unawaited(_torSubscription?.cancel());
});
return List.unmodifiable(_buffer);
return snapshot;
}
}