detached 4a84024

feat(webkit): add performance-optimized memory configuration system

commit
4a8402411f64497698409549e0b73cae3ff6e2a4
author
bamen · · 2025-09-12 13:56 UTC
parent
a462fed
signature
unsigned
2 files · +74 -0
M internal/config/config.go +62 -0
@@ -33,6 +33,7 @@ type Config struct {
3333 Appearance AppearanceConfig `mapstructure:"appearance" yaml:"appearance"`
3434 VideoAcceleration VideoAccelerationConfig `mapstructure:"video_acceleration" yaml:"video_acceleration"`
3535 CodecPreferences CodecConfig `mapstructure:"codec_preferences" yaml:"codec_preferences"`
36+ WebkitMemory WebkitMemoryConfig `mapstructure:"webkit_memory" yaml:"webkit_memory"`
3637 // RenderingMode controls GPU/CPU rendering selection for WebKit
3738 RenderingMode RenderingMode `mapstructure:"rendering_mode" yaml:"rendering_mode"`
3839 }
@@ -152,6 +153,35 @@ type CodecConfig struct {
152153 DisableTwitchCodecControl bool `mapstructure:"disable_twitch_codec_control" yaml:"disable_twitch_codec_control"`
153154 }
154155
156+// WebkitMemoryConfig holds WebKit memory optimization settings
157+type WebkitMemoryConfig struct {
158+ // Cache model (document_viewer | web_browser | primary_web_browser)
159+ CacheModel string `mapstructure:"cache_model" yaml:"cache_model"`
160+
161+ // Enable page cache for back/forward navigation
162+ EnablePageCache bool `mapstructure:"enable_page_cache" yaml:"enable_page_cache"`
163+
164+ // Memory limit in MB (0 = system default)
165+ MemoryLimitMB int `mapstructure:"memory_limit_mb" yaml:"memory_limit_mb"`
166+
167+ // Memory pressure thresholds (0.0-1.0)
168+ ConservativeThreshold float64 `mapstructure:"conservative_threshold" yaml:"conservative_threshold"`
169+ StrictThreshold float64 `mapstructure:"strict_threshold" yaml:"strict_threshold"`
170+ KillThreshold float64 `mapstructure:"kill_threshold" yaml:"kill_threshold"`
171+
172+ // Memory monitoring interval in seconds
173+ PollIntervalSeconds float64 `mapstructure:"poll_interval_seconds" yaml:"poll_interval_seconds"`
174+
175+ // Garbage collection interval in seconds (0 = disabled)
176+ EnableGCInterval int `mapstructure:"enable_gc_interval" yaml:"enable_gc_interval"`
177+
178+ // Process recycling threshold (number of page loads)
179+ ProcessRecycleThreshold int `mapstructure:"process_recycle_threshold" yaml:"process_recycle_threshold"`
180+
181+ // Enable memory monitoring logs
182+ EnableMemoryMonitoring bool `mapstructure:"enable_memory_monitoring" yaml:"enable_memory_monitoring"`
183+}
184+
155185 // Manager handles configuration loading, watching, and reloading.
156186 type Manager struct {
157187 config *Config
@@ -257,6 +287,26 @@ func NewManager() (*Manager, error) {
257287 }
258288 }
259289
290+ // WebKit memory environment variable bindings
291+ memoryEnvBindings := map[string]string{
292+ "webkit_memory.cache_model": "DUMBER_CACHE_MODEL",
293+ "webkit_memory.enable_page_cache": "DUMBER_ENABLE_PAGE_CACHE",
294+ "webkit_memory.memory_limit_mb": "DUMBER_MEMORY_LIMIT_MB",
295+ "webkit_memory.conservative_threshold": "DUMBER_MEMORY_CONSERVATIVE",
296+ "webkit_memory.strict_threshold": "DUMBER_MEMORY_STRICT",
297+ "webkit_memory.kill_threshold": "DUMBER_MEMORY_KILL",
298+ "webkit_memory.poll_interval_seconds": "DUMBER_MEMORY_POLL_INTERVAL",
299+ "webkit_memory.enable_gc_interval": "DUMBER_GC_INTERVAL",
300+ "webkit_memory.process_recycle_threshold": "DUMBER_RECYCLE_THRESHOLD",
301+ "webkit_memory.enable_memory_monitoring": "DUMBER_ENABLE_MEMORY_MONITORING",
302+ }
303+
304+ for key, env := range memoryEnvBindings {
305+ if err := v.BindEnv(key, env); err != nil {
306+ return nil, fmt.Errorf("failed to bind environment variable %s: %w", env, err)
307+ }
308+ }
309+
260310 return &Manager{
261311 viper: v,
262312 callbacks: make([]func(*Config), 0),
@@ -500,6 +550,18 @@ func (m *Manager) setDefaults() {
500550 m.viper.SetDefault("codec_preferences.av1_max_resolution", defaults.CodecPreferences.AV1MaxResolution)
501551 m.viper.SetDefault("codec_preferences.disable_twitch_codec_control", defaults.CodecPreferences.DisableTwitchCodecControl)
502552
553+ // WebKit memory defaults
554+ m.viper.SetDefault("webkit_memory.cache_model", defaults.WebkitMemory.CacheModel)
555+ m.viper.SetDefault("webkit_memory.enable_page_cache", defaults.WebkitMemory.EnablePageCache)
556+ m.viper.SetDefault("webkit_memory.memory_limit_mb", defaults.WebkitMemory.MemoryLimitMB)
557+ m.viper.SetDefault("webkit_memory.conservative_threshold", defaults.WebkitMemory.ConservativeThreshold)
558+ m.viper.SetDefault("webkit_memory.strict_threshold", defaults.WebkitMemory.StrictThreshold)
559+ m.viper.SetDefault("webkit_memory.kill_threshold", defaults.WebkitMemory.KillThreshold)
560+ m.viper.SetDefault("webkit_memory.poll_interval_seconds", defaults.WebkitMemory.PollIntervalSeconds)
561+ m.viper.SetDefault("webkit_memory.enable_gc_interval", defaults.WebkitMemory.EnableGCInterval)
562+ m.viper.SetDefault("webkit_memory.process_recycle_threshold", defaults.WebkitMemory.ProcessRecycleThreshold)
563+ m.viper.SetDefault("webkit_memory.enable_memory_monitoring", defaults.WebkitMemory.EnableMemoryMonitoring)
564+
503565 // Rendering defaults
504566 m.viper.SetDefault("rendering_mode", string(RenderingModeAuto))
505567 }
@@ -33,6 +33,7 @@ type Config struct {
33 Appearance AppearanceConfig `mapstructure:"appearance" yaml:"appearance"`33 Appearance AppearanceConfig `mapstructure:"appearance" yaml:"appearance"`
34 VideoAcceleration VideoAccelerationConfig `mapstructure:"video_acceleration" yaml:"video_acceleration"`34 VideoAcceleration VideoAccelerationConfig `mapstructure:"video_acceleration" yaml:"video_acceleration"`
35 CodecPreferences CodecConfig `mapstructure:"codec_preferences" yaml:"codec_preferences"`35 CodecPreferences CodecConfig `mapstructure:"codec_preferences" yaml:"codec_preferences"`
36+ WebkitMemory WebkitMemoryConfig `mapstructure:"webkit_memory" yaml:"webkit_memory"`
36 // RenderingMode controls GPU/CPU rendering selection for WebKit37 // RenderingMode controls GPU/CPU rendering selection for WebKit
37 RenderingMode RenderingMode `mapstructure:"rendering_mode" yaml:"rendering_mode"`38 RenderingMode RenderingMode `mapstructure:"rendering_mode" yaml:"rendering_mode"`
38 }39 }
@@ -152,6 +153,35 @@ type CodecConfig struct {
152 DisableTwitchCodecControl bool `mapstructure:"disable_twitch_codec_control" yaml:"disable_twitch_codec_control"`153 DisableTwitchCodecControl bool `mapstructure:"disable_twitch_codec_control" yaml:"disable_twitch_codec_control"`
153 }154 }
154 155
156+// WebkitMemoryConfig holds WebKit memory optimization settings
157+type WebkitMemoryConfig struct {
158+ // Cache model (document_viewer | web_browser | primary_web_browser)
159+ CacheModel string `mapstructure:"cache_model" yaml:"cache_model"`
160+
161+ // Enable page cache for back/forward navigation
162+ EnablePageCache bool `mapstructure:"enable_page_cache" yaml:"enable_page_cache"`
163+
164+ // Memory limit in MB (0 = system default)
165+ MemoryLimitMB int `mapstructure:"memory_limit_mb" yaml:"memory_limit_mb"`
166+
167+ // Memory pressure thresholds (0.0-1.0)
168+ ConservativeThreshold float64 `mapstructure:"conservative_threshold" yaml:"conservative_threshold"`
169+ StrictThreshold float64 `mapstructure:"strict_threshold" yaml:"strict_threshold"`
170+ KillThreshold float64 `mapstructure:"kill_threshold" yaml:"kill_threshold"`
171+
172+ // Memory monitoring interval in seconds
173+ PollIntervalSeconds float64 `mapstructure:"poll_interval_seconds" yaml:"poll_interval_seconds"`
174+
175+ // Garbage collection interval in seconds (0 = disabled)
176+ EnableGCInterval int `mapstructure:"enable_gc_interval" yaml:"enable_gc_interval"`
177+
178+ // Process recycling threshold (number of page loads)
179+ ProcessRecycleThreshold int `mapstructure:"process_recycle_threshold" yaml:"process_recycle_threshold"`
180+
181+ // Enable memory monitoring logs
182+ EnableMemoryMonitoring bool `mapstructure:"enable_memory_monitoring" yaml:"enable_memory_monitoring"`
183+}
184+
155 // Manager handles configuration loading, watching, and reloading.185 // Manager handles configuration loading, watching, and reloading.
156 type Manager struct {186 type Manager struct {
157 config *Config187 config *Config
@@ -257,6 +287,26 @@ func NewManager() (*Manager, error) {
257 }287 }
258 }288 }
259 289
290+ // WebKit memory environment variable bindings
291+ memoryEnvBindings := map[string]string{
292+ "webkit_memory.cache_model": "DUMBER_CACHE_MODEL",
293+ "webkit_memory.enable_page_cache": "DUMBER_ENABLE_PAGE_CACHE",
294+ "webkit_memory.memory_limit_mb": "DUMBER_MEMORY_LIMIT_MB",
295+ "webkit_memory.conservative_threshold": "DUMBER_MEMORY_CONSERVATIVE",
296+ "webkit_memory.strict_threshold": "DUMBER_MEMORY_STRICT",
297+ "webkit_memory.kill_threshold": "DUMBER_MEMORY_KILL",
298+ "webkit_memory.poll_interval_seconds": "DUMBER_MEMORY_POLL_INTERVAL",
299+ "webkit_memory.enable_gc_interval": "DUMBER_GC_INTERVAL",
300+ "webkit_memory.process_recycle_threshold": "DUMBER_RECYCLE_THRESHOLD",
301+ "webkit_memory.enable_memory_monitoring": "DUMBER_ENABLE_MEMORY_MONITORING",
302+ }
303+
304+ for key, env := range memoryEnvBindings {
305+ if err := v.BindEnv(key, env); err != nil {
306+ return nil, fmt.Errorf("failed to bind environment variable %s: %w", env, err)
307+ }
308+ }
309+
260 return &Manager{310 return &Manager{
261 viper: v,311 viper: v,
262 callbacks: make([]func(*Config), 0),312 callbacks: make([]func(*Config), 0),
@@ -500,6 +550,18 @@ func (m *Manager) setDefaults() {
500 m.viper.SetDefault("codec_preferences.av1_max_resolution", defaults.CodecPreferences.AV1MaxResolution)550 m.viper.SetDefault("codec_preferences.av1_max_resolution", defaults.CodecPreferences.AV1MaxResolution)
501 m.viper.SetDefault("codec_preferences.disable_twitch_codec_control", defaults.CodecPreferences.DisableTwitchCodecControl)551 m.viper.SetDefault("codec_preferences.disable_twitch_codec_control", defaults.CodecPreferences.DisableTwitchCodecControl)
502 552
553+ // WebKit memory defaults
554+ m.viper.SetDefault("webkit_memory.cache_model", defaults.WebkitMemory.CacheModel)
555+ m.viper.SetDefault("webkit_memory.enable_page_cache", defaults.WebkitMemory.EnablePageCache)
556+ m.viper.SetDefault("webkit_memory.memory_limit_mb", defaults.WebkitMemory.MemoryLimitMB)
557+ m.viper.SetDefault("webkit_memory.conservative_threshold", defaults.WebkitMemory.ConservativeThreshold)
558+ m.viper.SetDefault("webkit_memory.strict_threshold", defaults.WebkitMemory.StrictThreshold)
559+ m.viper.SetDefault("webkit_memory.kill_threshold", defaults.WebkitMemory.KillThreshold)
560+ m.viper.SetDefault("webkit_memory.poll_interval_seconds", defaults.WebkitMemory.PollIntervalSeconds)
561+ m.viper.SetDefault("webkit_memory.enable_gc_interval", defaults.WebkitMemory.EnableGCInterval)
562+ m.viper.SetDefault("webkit_memory.process_recycle_threshold", defaults.WebkitMemory.ProcessRecycleThreshold)
563+ m.viper.SetDefault("webkit_memory.enable_memory_monitoring", defaults.WebkitMemory.EnableMemoryMonitoring)
564+
503 // Rendering defaults565 // Rendering defaults
504 m.viper.SetDefault("rendering_mode", string(RenderingModeAuto))566 m.viper.SetDefault("rendering_mode", string(RenderingModeAuto))
505 }567 }
M internal/config/defaults.go +12 -0
@@ -119,6 +119,18 @@ func DefaultConfig() *Config {
119119 AV1MaxResolution: "1080p", // Optimal AV1 up to 1080p, fallback to VP9 for higher res
120120 DisableTwitchCodecControl: true, // Disable codec control on Twitch by default (prevents theater/fullscreen freezing)
121121 },
122+ WebkitMemory: WebkitMemoryConfig{
123+ CacheModel: "web_browser", // Aggressive caching for fast page loads
124+ EnablePageCache: true, // Instant back/forward navigation
125+ MemoryLimitMB: 0, // Use system default
126+ ConservativeThreshold: 0.4, // Start cleanup at 40%
127+ StrictThreshold: 0.6, // Strict cleanup at 60%
128+ KillThreshold: 0.8, // Kill processes at 80%
129+ PollIntervalSeconds: 45.0, // Check every 45 seconds
130+ EnableGCInterval: 120, // GC every 2 minutes
131+ ProcessRecycleThreshold: 50, // Recycle after 50 page loads
132+ EnableMemoryMonitoring: true, // Monitor for production tuning
133+ },
122134 RenderingMode: RenderingModeAuto,
123135 }
124136 }
@@ -119,6 +119,18 @@ func DefaultConfig() *Config {
119 AV1MaxResolution: "1080p", // Optimal AV1 up to 1080p, fallback to VP9 for higher res119 AV1MaxResolution: "1080p", // Optimal AV1 up to 1080p, fallback to VP9 for higher res
120 DisableTwitchCodecControl: true, // Disable codec control on Twitch by default (prevents theater/fullscreen freezing)120 DisableTwitchCodecControl: true, // Disable codec control on Twitch by default (prevents theater/fullscreen freezing)
121 },121 },
122+ WebkitMemory: WebkitMemoryConfig{
123+ CacheModel: "web_browser", // Aggressive caching for fast page loads
124+ EnablePageCache: true, // Instant back/forward navigation
125+ MemoryLimitMB: 0, // Use system default
126+ ConservativeThreshold: 0.4, // Start cleanup at 40%
127+ StrictThreshold: 0.6, // Strict cleanup at 60%
128+ KillThreshold: 0.8, // Kill processes at 80%
129+ PollIntervalSeconds: 45.0, // Check every 45 seconds
130+ EnableGCInterval: 120, // GC every 2 minutes
131+ ProcessRecycleThreshold: 50, // Recycle after 50 page loads
132+ EnableMemoryMonitoring: true, // Monitor for production tuning
133+ },
122 RenderingMode: RenderingModeAuto,134 RenderingMode: RenderingModeAuto,
123 }135 }
124 }136 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close