servo/components/constellation/tracing.rs
Jonathan Schwender f4dd2960b8
Add direct script to embedder channel (#39039)
This PR **removes** `ScriptToConstellationMessage::ForwardToEmbedder`,
and replaces it with an explicit `ScriptToEmbedderChannel`. This new
channel is based on `GenericCallback` and in single-process mode will
directly send the message the to the embedder and wake it. In
multi-process mode, the message is routed via the ROUTER, since waking
is only possible from the same process currently. This means in
multi-process mode there are likely no direct perf benefits, since we
still need to hop the message over the ROUTER (instead of over the
constellation).
In single-process mode we can directly send the message to the embedder,
which should provide a noticable latency improvement in all cases where
script is blocked waiting on the embedder to reply.

This does not change the way the embedder receives messages - the
receiving end is unchanged.

## How was sending messages to the embedder working before?

1. Script wraps it's message to the embedder in
`ScriptToConstellationMessage::ForwardToEmbedder` and sends it to
constellation.
2. The [constellation event loop] receives the message in
[handle_request]
3. If deserialization fails, [an error is logged and the message is
ignored]
4. Since our message came from script, it is handle in
[handle_request_from_script]
5. The message is logged with trace log level
6. If the pipeline is closed, [a warning is logged and the message
ignored]
7. The wrapped `EmbedderMsg` [is forwarded to the embedder]. Sending the
message also invokes `wake()` on the embedder eventloop waker.

[constellation event loop]:
2e1b2e7260/components/constellation/constellation.rs (L755)

[handle request]:
2e1b2e7260/components/constellation/constellation.rs (L1182)

[an error is logged and the message is ignored]:
2e1b2e7260/components/constellation/constellation.rs (L1252)

[handle_request_from_script]:
https://github.com/servo/servo/blob/main/components/constellation/constellation.rs#L1590
 
[a warning is logged and the message ignored]:
2e1b2e7260/components/constellation/constellation.rs (L1599)

[is forwarded to the embedder]:
2e1b2e7260/components/constellation/constellation.rs (L1701)

Testing: Communication between Script and Embedder is extensive, so this
should be covered by existing tests.

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2025-09-02 06:33:44 +00:00

188 lines
10 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/// Log an event from compositor at trace level.
/// - To disable tracing: RUST_LOG='constellation<compositor@=off'
/// - To enable tracing: RUST_LOG='constellation<compositor@'
/// - Recommended filters when tracing is enabled:
/// - constellation<compositor@ForwardEvent(MouseMoveEvent)=off
/// - constellation<compositor@LogEntry=off
/// - constellation<compositor@ReadyToPresent=off
macro_rules! trace_msg_from_compositor {
// This macro only exists to put the docs in the same file as the target prefix,
// so the macro definition is always the same.
($event:expr, $($rest:tt)+) => {
::log::trace!(target: $crate::tracing::LogTarget::log_target(&$event), $($rest)+)
};
}
/// Log an event from script at trace level.
/// - To disable tracing: RUST_LOG='constellation<script@=off'
/// - To enable tracing: RUST_LOG='constellation<script@'
/// - Recommended filters when tracing is enabled:
/// - constellation<script@LogEntry=off
macro_rules! trace_script_msg {
// This macro only exists to put the docs in the same file as the target prefix,
// so the macro definition is always the same.
($event:expr, $($rest:tt)+) => {
::log::trace!(target: $crate::tracing::LogTarget::log_target(&$event), $($rest)+)
};
}
/// Get the log target for an event, as a static string.
pub(crate) trait LogTarget {
fn log_target(&self) -> &'static str;
}
mod from_compositor {
use embedder_traits::InputEvent;
use super::LogTarget;
macro_rules! target {
($($name:literal)+) => {
concat!("constellation<compositor@", $($name),+)
};
}
impl LogTarget for constellation_traits::EmbedderToConstellationMessage {
fn log_target(&self) -> &'static str {
match self {
Self::Exit => target!("Exit"),
Self::IsReadyToSaveImage(..) => target!("IsReadyToSaveImage"),
Self::AllowNavigationResponse(..) => target!("AllowNavigationResponse"),
Self::LoadUrl(..) => target!("LoadUrl"),
Self::ClearCache => target!("ClearCache"),
Self::TraverseHistory(..) => target!("TraverseHistory"),
Self::ChangeViewportDetails(..) => target!("ChangeViewportDetails"),
Self::ThemeChange(..) => target!("ThemeChange"),
Self::TickAnimation(..) => target!("TickAnimation"),
Self::WebDriverCommand(..) => target!("WebDriverCommand"),
Self::Reload(..) => target!("Reload"),
Self::LogEntry(..) => target!("LogEntry"),
Self::NewWebView(..) => target!("NewWebView"),
Self::CloseWebView(..) => target!("CloseWebView"),
Self::SendError(..) => target!("SendError"),
Self::FocusWebView(..) => target!("FocusWebView"),
Self::BlurWebView => target!("BlurWebView"),
Self::ForwardInputEvent(_webview_id, event, ..) => event.log_target(),
Self::RefreshCursor(..) => target!("RefreshCursor"),
Self::ToggleProfiler(..) => target!("EnableProfiler"),
Self::ExitFullScreen(_) => target!("ExitFullScreen"),
Self::MediaSessionAction(_) => target!("MediaSessionAction"),
Self::SetWebViewThrottled(_, _) => target!("SetWebViewThrottled"),
Self::SetScrollStates(..) => target!("SetScrollStates"),
Self::PaintMetric(..) => target!("PaintMetric"),
Self::EvaluateJavaScript(..) => target!("EvaluateJavaScript"),
Self::CreateMemoryReport(..) => target!("CreateMemoryReport"),
Self::SendImageKeysForPipeline(..) => target!("SendImageKeysForPipeline"),
Self::SetWebDriverResponseSender(..) => target!("SetWebDriverResponseSender"),
Self::PreferencesUpdated(..) => target!("PreferencesUpdated"),
Self::NoLongerWaitingOnAsynchronousImageUpdates(..) => {
target!("NoLongerWaitingOnCanvas")
},
}
}
}
impl LogTarget for InputEvent {
fn log_target(&self) -> &'static str {
macro_rules! target_variant {
($name:literal) => {
target!("ForwardInputEvent(" $name ")")
};
}
match self {
InputEvent::EditingAction(..) => target_variant!("EditingAction"),
InputEvent::Gamepad(..) => target_variant!("Gamepad"),
InputEvent::Ime(..) => target_variant!("Ime"),
InputEvent::Keyboard(..) => target_variant!("Keyboard"),
InputEvent::MouseButton(..) => target_variant!("MouseButton"),
InputEvent::MouseMove(..) => target_variant!("MouseMove"),
InputEvent::MouseLeftViewport(..) => target_variant!("MouseLeftViewport"),
InputEvent::Touch(..) => target_variant!("Touch"),
InputEvent::Wheel(..) => target_variant!("Wheel"),
InputEvent::Scroll(..) => target_variant!("Scroll"),
}
}
}
}
mod from_script {
use super::LogTarget;
macro_rules! target {
($($name:literal)+) => {
concat!("constellation<script@", $($name),+)
};
}
impl LogTarget for constellation_traits::ScriptToConstellationMessage {
fn log_target(&self) -> &'static str {
match self {
Self::CompleteMessagePortTransfer(..) => target!("CompleteMessagePortTransfer"),
Self::MessagePortTransferResult(..) => target!("MessagePortTransferResult"),
Self::NewMessagePort(..) => target!("NewMessagePort"),
Self::NewMessagePortRouter(..) => target!("NewMessagePortRouter"),
Self::RemoveMessagePortRouter(..) => target!("RemoveMessagePortRouter"),
Self::RerouteMessagePort(..) => target!("RerouteMessagePort"),
Self::MessagePortShipped(..) => target!("MessagePortShipped"),
Self::EntanglePorts(..) => target!("EntanglePorts"),
Self::DisentanglePorts(..) => target!("DisentanglePorts"),
Self::NewBroadcastChannelRouter(..) => target!("NewBroadcastChannelRouter"),
Self::RemoveBroadcastChannelRouter(..) => target!("RemoveBroadcastChannelRouter"),
Self::NewBroadcastChannelNameInRouter(..) => {
target!("NewBroadcastChannelNameInRouter")
},
Self::RemoveBroadcastChannelNameInRouter(..) => {
target!("RemoveBroadcastChannelNameInRouter")
},
Self::ScheduleBroadcast(..) => target!("ScheduleBroadcast"),
Self::BroadcastStorageEvent(..) => target!("BroadcastStorageEvent"),
Self::ChangeRunningAnimationsState(..) => target!("ChangeRunningAnimationsState"),
Self::CreateCanvasPaintThread(..) => target!("CreateCanvasPaintThread"),
Self::Focus(..) => target!("Focus"),
Self::FocusRemoteDocument(..) => target!("FocusRemoteDocument"),
Self::GetTopForBrowsingContext(..) => target!("GetTopForBrowsingContext"),
Self::GetBrowsingContextInfo(..) => target!("GetBrowsingContextInfo"),
Self::GetChildBrowsingContextId(..) => target!("GetChildBrowsingContextId"),
Self::LoadComplete => target!("LoadComplete"),
Self::LoadUrl(..) => target!("LoadUrl"),
Self::AbortLoadUrl => target!("AbortLoadUrl"),
Self::PostMessage { .. } => target!("PostMessage"),
Self::NavigatedToFragment(..) => target!("NavigatedToFragment"),
Self::TraverseHistory(..) => target!("TraverseHistory"),
Self::PushHistoryState(..) => target!("PushHistoryState"),
Self::ReplaceHistoryState(..) => target!("ReplaceHistoryState"),
Self::JointSessionHistoryLength(..) => target!("JointSessionHistoryLength"),
Self::RemoveIFrame(..) => target!("RemoveIFrame"),
Self::SetThrottledComplete(..) => target!("SetThrottledComplete"),
Self::ScriptLoadedURLInIFrame(..) => target!("ScriptLoadedURLInIFrame"),
Self::ScriptNewIFrame(..) => target!("ScriptNewIFrame"),
Self::CreateAuxiliaryWebView(..) => target!("ScriptNewAuxiliary"),
Self::ActivateDocument => target!("ActivateDocument"),
Self::SetDocumentState(..) => target!("SetDocumentState"),
Self::SetLayoutEpoch(..) => target!("SetLayoutEpoch"),
Self::SetFinalUrl(..) => target!("SetFinalUrl"),
Self::TouchEventProcessed(..) => target!("TouchEventProcessed"),
Self::LogEntry(..) => target!("LogEntry"),
Self::DiscardDocument => target!("DiscardDocument"),
Self::DiscardTopLevelBrowsingContext => target!("DiscardTopLevelBrowsingContext"),
Self::PipelineExited => target!("PipelineExited"),
Self::ForwardDOMMessage(..) => target!("ForwardDOMMessage"),
Self::ScheduleJob(..) => target!("ScheduleJob"),
Self::MediaSessionEvent(..) => target!("MediaSessionEvent"),
#[cfg(feature = "webgpu")]
Self::RequestAdapter(..) => target!("RequestAdapter"),
#[cfg(feature = "webgpu")]
Self::GetWebGPUChan(..) => target!("GetWebGPUChan"),
Self::TitleChanged(..) => target!("TitleChanged"),
Self::IFrameSizes(..) => target!("IFrameSizes"),
Self::ReportMemory(..) => target!("ReportMemory"),
Self::WebDriverInputComplete(..) => target!("WebDriverInputComplete"),
Self::FinishJavaScriptEvaluation(..) => target!("FinishJavaScriptEvaluation"),
}
}
}
}