perf(app): suppress repeated web metadata updates

This commit is contained in:
2026-05-16 05:03:43 -04:00
parent 76a56decff
commit 0d755af005
4 changed files with 83 additions and 10 deletions
+2 -4
View File
@@ -10,7 +10,6 @@ use super::{
web_surface_cadence::IDLE_POLL_INTERVAL,
web_surface_frame::WebSurfaceFrame,
web_surface_geometry::{WebSurfaceClickPoint, WebSurfaceScrollDelta, WebSurfaceSize},
web_surface_metadata::WebSurfacePageMetadata,
web_surface_permissions::WebSurfaceSitePermission,
web_surface_runtime::{WebSurfaceRuntime, WebSurfaceRuntimeFrame},
web_surface_state::{
@@ -118,9 +117,8 @@ impl WebSurfaceStore {
}
continue;
}
result
.page_metadata
.extend(WebSurfacePageMetadata::from_frame(&tab_id, &frame));
let metadata = self.surface_mut(&tab_id).changed_page_metadata(&tab_id, &frame);
result.page_metadata.extend(metadata);
if self
.surfaces
.get(&tab_id)
@@ -2,6 +2,30 @@ use ely_domain::TabId;
use super::web_surface_frame::WebSurfaceFrame;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub(super) struct WebSurfaceMetadataTracker {
last_title: Option<String>,
last_loaded_url: Option<String>,
}
impl WebSurfaceMetadataTracker {
pub(super) fn changed_metadata_for(
&mut self,
tab_id: &TabId,
frame: &WebSurfaceFrame,
) -> Option<WebSurfacePageMetadata> {
let title = frame.title().map(str::to_string);
let loaded_url = frame.loaded_url().map(str::to_string);
if self.last_title == title && self.last_loaded_url == loaded_url {
return None;
}
self.last_title = title.clone();
self.last_loaded_url = loaded_url.clone();
WebSurfacePageMetadata::from_parts(tab_id, title, loaded_url)
}
}
/// One page's worth of metadata observed in a Ready frame. The
/// controller applies these to the `BrowserTab` after the frame has
/// been swapped into the surface state. Title and favicon are
@@ -15,10 +39,13 @@ pub(super) struct WebSurfacePageMetadata {
}
impl WebSurfacePageMetadata {
pub(super) fn from_frame(tab_id: &TabId, frame: &WebSurfaceFrame) -> Option<Self> {
let title = frame.title().map(str::to_string);
let favicon_url = frame
.loaded_url()
fn from_parts(
tab_id: &TabId,
title: Option<String>,
loaded_url: Option<String>,
) -> Option<Self> {
let favicon_url = loaded_url
.as_deref()
.and_then(|loaded| ely_domain::UrlText::parse(loaded).ok())
.and_then(|url| url.favicon_url());
if title.is_none() && favicon_url.is_none() {
@@ -27,3 +54,41 @@ impl WebSurfacePageMetadata {
Some(Self { tab_id: tab_id.clone(), title, favicon_url })
}
}
#[cfg(test)]
mod tests {
use std::error::Error;
use ely_domain::TabId;
use super::*;
use crate::{
services::servo_live::ServoLiveFrame,
shell::{web_surface_frame::WebSurfaceFrame, web_surface_geometry::WebSurfaceScrollOffset},
};
#[test]
fn repeated_frame_metadata_emits_once() -> Result<(), Box<dyn Error>> {
let tab_id = TabId::new();
let frame = frame()?;
let mut tracker = WebSurfaceMetadataTracker::default();
let first = tracker.changed_metadata_for(&tab_id, &frame);
let second = tracker.changed_metadata_for(&tab_id, &frame);
assert!(first.is_some());
assert_eq!(second, None);
Ok(())
}
fn frame() -> Result<WebSurfaceFrame, Box<dyn Error>> {
let rgba_pixel = vec![255u8, 255, 255, 255];
let live = ServoLiveFrame::for_test(1, 1, rgba_pixel);
Ok(WebSurfaceFrame::from_live_frame(
"https://example.com/".to_string(),
WebSurfaceScrollOffset::default(),
100,
live,
)?)
}
}
@@ -176,7 +176,7 @@ fn identical_ready_software_frame_keeps_tick_unchanged() -> Result<(), String> {
let second_tick = store.tick(&visible_tabs);
assert!(!second_tick.changed);
assert_eq!(second_tick.page_metadata.len(), 1);
assert_eq!(second_tick.page_metadata.len(), 0);
assert_eq!(second_tick.url_changes.len(), 1);
assert_eq!(REPEATED_FRAME_ENSURE_COUNT.load(Ordering::SeqCst), 2);
Ok(())
+11 -1
View File
@@ -9,7 +9,7 @@ use super::{
web_surface_geometry::{
WebSurfaceClickPoint, WebSurfaceScrollDelta, WebSurfaceScrollOffset, WebSurfaceSize,
},
web_surface_metadata::WebSurfacePageMetadata,
web_surface_metadata::{WebSurfaceMetadataTracker, WebSurfacePageMetadata},
web_surface_permissions::WebSurfaceSitePermission,
web_surface_runtime::WebSurfaceUrlChange,
};
@@ -137,6 +137,7 @@ pub(super) struct PerTabSurface {
pub(super) typed_text: Option<WebSurfaceTextInputState>,
pub(super) state: Option<WebSurfaceState>,
last_input_flushed_at: Option<Instant>,
metadata_tracker: WebSurfaceMetadataTracker,
}
impl PerTabSurface {
@@ -155,6 +156,7 @@ impl PerTabSurface {
typed_text: None,
state: None,
last_input_flushed_at: None,
metadata_tracker: WebSurfaceMetadataTracker::default(),
}
}
@@ -195,6 +197,14 @@ impl PerTabSurface {
}
}
pub(super) fn changed_page_metadata(
&mut self,
tab_id: &TabId,
frame: &WebSurfaceFrame,
) -> Option<WebSurfacePageMetadata> {
self.metadata_tracker.changed_metadata_for(tab_id, frame)
}
fn has_pending_input(&self) -> bool {
self.hover_point.is_some()
|| self.click_point.is_some()