Created
May 5, 2025 14:37
-
-
Save jrmuizel/c11b535444192a01dc621213312f9d8a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| commit 815f5a4bd71cdd73dad134125dde89c8e6ec45bd | |
| Author: Jeff Muizelaar <jmuizelaar@mozilla.com> | |
| Date: Fri Nov 15 10:38:17 2024 +0100 | |
| Rust flow | |
| diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp | |
| index e6bba66b6fff9..ee6fc53401720 100644 | |
| --- a/netwerk/protocol/http/nsHttpTransaction.cpp | |
| +++ b/netwerk/protocol/http/nsHttpTransaction.cpp | |
| @@ -73,20 +73,26 @@ | |
| using namespace mozilla::net; | |
| namespace mozilla::net { | |
| //----------------------------------------------------------------------------- | |
| // nsHttpTransaction <public> | |
| //----------------------------------------------------------------------------- | |
| nsHttpTransaction::nsHttpTransaction() { | |
| LOG(("Creating nsHttpTransaction @%p\n", this)); | |
| + profiler_add_marker( | |
| + mozilla::ProfilerString8View::WrapNullTerminatedString("nsHTTPTransaction"), | |
| + mozilla::baseprofiler::category::NETWORK, | |
| + {mozilla::MarkerTiming::InstantNow(), | |
| + }, | |
| + FlowMarker{}, Flow::FromPointer(this)); | |
| #ifdef MOZ_VALGRIND | |
| memset(&mSelfAddr, 0, sizeof(NetAddr)); | |
| memset(&mPeerAddr, 0, sizeof(NetAddr)); | |
| #endif | |
| mSelfAddr.raw.family = PR_AF_UNSPEC; | |
| mPeerAddr.raw.family = PR_AF_UNSPEC; | |
| } | |
| void nsHttpTransaction::ResumeReading() { | |
| diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs | |
| index 761c04e90c630..59e1740579042 100644 | |
| --- a/servo/ports/geckolib/glue.rs | |
| +++ b/servo/ports/geckolib/glue.rs | |
| @@ -160,20 +160,24 @@ use style::values::generics::easing::BeforeFlag; | |
| use style::values::generics::length::AnchorResolutionResult; | |
| use style::values::resolved; | |
| use style::values::specified::intersection_observer::IntersectionObserverMargin; | |
| use style::values::specified::source_size_list::SourceSizeList; | |
| use style::values::specified::{AbsoluteLength, NoCalcLength}; | |
| use style::values::{specified, AtomIdent, CustomIdent, KeyframesName}; | |
| use style::values::specified::svg_path::PathCommand; | |
| use style_traits::{CssWriter, ParseError, ParsingMode, ToCss}; | |
| use thin_vec::ThinVec as nsTArray; | |
| use to_shmem::SharedMemoryBuilder; | |
| +use gecko_profiler::Flow; | |
| +use gecko_profiler::MarkerOptions; | |
| +use gecko_profiler::MarkerStack; | |
| + | |
| trait ClosureHelper { | |
| fn invoke(&self, property_id: Option<NonCustomPropertyId>); | |
| } | |
| const NO_MUTATION_CLOSURE : DeclarationBlockMutationClosure = DeclarationBlockMutationClosure { | |
| data: std::ptr::null_mut(), | |
| function: None, | |
| }; | |
| @@ -1673,35 +1677,46 @@ pub unsafe extern "C" fn Servo_StyleSheet_FromUTF8BytesAsync( | |
| mode: SheetParsingMode, | |
| quirks_mode: nsCompatibility, | |
| should_record_use_counters: bool, | |
| allow_import_rules: AllowImportRules, | |
| ) { | |
| let load_data = RefPtr::new(load_data); | |
| let extra_data = UrlExtraData::new(extra_data); | |
| let mut sheet_bytes = nsCString::new(); | |
| sheet_bytes.assign(bytes); | |
| + // we use the sheet_bytes allocation as our flow marker | |
| + let sheet_bytes_flow = Flow::from_pointer(sheet_bytes.as_ref().as_ptr()); | |
| let async_parser = AsyncStylesheetParser::new( | |
| load_data, | |
| extra_data, | |
| sheet_bytes, | |
| mode_to_origin(mode), | |
| quirks_mode.into(), | |
| should_record_use_counters, | |
| allow_import_rules, | |
| ); | |
| + gecko_profiler::add_marker("StyleParseQueue", | |
| + gecko_profiler::gecko_profiler_category!(Layout), | |
| + MarkerOptions { timing: Default::default(), stack: MarkerStack::Full }, | |
| + sheet_bytes_flow); | |
| if let Some(thread_pool) = STYLE_THREAD_POOL.pool().as_ref() { | |
| - thread_pool.spawn(|| { | |
| + thread_pool.spawn(move || { | |
| gecko_profiler_label!(Layout, CSSParsing); | |
| + auto_profiler_flow_marker!("StyleParseDo", | |
| + gecko_profiler::gecko_profiler_category!(Graphics), | |
| + Default::default(), | |
| + sheet_bytes_flow); | |
| async_parser.parse(); | |
| + | |
| }); | |
| } else { | |
| async_parser.parse(); | |
| } | |
| } | |
| #[no_mangle] | |
| pub unsafe extern "C" fn Servo_ShutdownThreadPool() { | |
| debug_assert!(is_main_thread() && !is_in_servo_traversal()); | |
| StyleThreadPool::shutdown(); | |
| diff --git a/tools/profiler/core/ProfilerBindings.cpp b/tools/profiler/core/ProfilerBindings.cpp | |
| index 833facba00d87..db326a8c182e2 100644 | |
| --- a/tools/profiler/core/ProfilerBindings.cpp | |
| +++ b/tools/profiler/core/ProfilerBindings.cpp | |
| @@ -179,20 +179,26 @@ void gecko_profiler_marker_schema_set_table_label( | |
| } | |
| void gecko_profiler_marker_schema_set_all_labels(mozilla::MarkerSchema* aSchema, | |
| const char* aLabel, | |
| size_t aLabelLength) { | |
| #ifdef MOZ_GECKO_PROFILER | |
| aSchema->SetAllLabels(std::string(aLabel, aLabelLength)); | |
| #endif | |
| } | |
| +void gecko_profiler_marker_schema_set_is_stack_based(mozilla::MarkerSchema* aSchema) { | |
| +#ifdef MOZ_GECKO_PROFILER | |
| + aSchema->SetIsStackBased(); | |
| +#endif | |
| +} | |
| + | |
| void gecko_profiler_marker_schema_add_key_format( | |
| mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, | |
| mozilla::MarkerSchema::Format aFormat) { | |
| #ifdef MOZ_GECKO_PROFILER | |
| aSchema->AddKeyFormat(std::string(aKey, aKeyLength), aFormat); | |
| #endif | |
| } | |
| void gecko_profiler_marker_schema_add_key_label_format( | |
| mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, | |
| diff --git a/tools/profiler/public/ProfilerBindings.h b/tools/profiler/public/ProfilerBindings.h | |
| index 3ae6a16206103..3cfe6d02059aa 100644 | |
| --- a/tools/profiler/public/ProfilerBindings.h | |
| +++ b/tools/profiler/public/ProfilerBindings.h | |
| @@ -85,20 +85,21 @@ void gecko_profiler_destruct_marker_schema( | |
| // MarkerSchema methods for adding labels. | |
| void gecko_profiler_marker_schema_set_chart_label( | |
| mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength); | |
| void gecko_profiler_marker_schema_set_tooltip_label( | |
| mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength); | |
| void gecko_profiler_marker_schema_set_table_label( | |
| mozilla::MarkerSchema* aSchema, const char* aLabel, size_t aLabelLength); | |
| void gecko_profiler_marker_schema_set_all_labels(mozilla::MarkerSchema* aSchema, | |
| const char* aLabel, | |
| size_t aLabelLength); | |
| +void gecko_profiler_marker_schema_set_is_stack_based(mozilla::MarkerSchema* aSchema); | |
| // MarkerSchema methods for adding key/key-label values. | |
| void gecko_profiler_marker_schema_add_key_format( | |
| mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, | |
| mozilla::MarkerSchema::Format aFormat); | |
| void gecko_profiler_marker_schema_add_key_label_format( | |
| mozilla::MarkerSchema* aSchema, const char* aKey, size_t aKeyLength, | |
| const char* aLabel, size_t aLabelLength, | |
| mozilla::MarkerSchema::Format aFormat); | |
| void gecko_profiler_marker_schema_add_key_format_searchable( | |
| diff --git a/tools/profiler/rust-api/src/marker/mod.rs b/tools/profiler/rust-api/src/marker/mod.rs | |
| index 2d796ac8753a9..7e0b34a3ec506 100644 | |
| --- a/tools/profiler/rust-api/src/marker/mod.rs | |
| +++ b/tools/profiler/rust-api/src/marker/mod.rs | |
| @@ -538,10 +538,149 @@ macro_rules! auto_profiler_marker_tracing { | |
| }; | |
| } | |
| #[cfg(not(feature = "enabled"))] | |
| #[macro_export] | |
| macro_rules! auto_profiler_marker_tracing { | |
| ($name:expr, $category:expr,$options:expr, $payload:expr) => { | |
| // Do nothing if the profiler is not enabled | |
| }; | |
| } | |
| + | |
| +/// Flow marker type for Rust code. | |
| +/// This must be kept in sync with the `mozilla::baseprofiler::markers::Tracing` | |
| +/// C++ counterpart. | |
| +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] | |
| +pub struct Flow(pub u64); | |
| + | |
| +impl Flow { | |
| + pub fn from_pointer<T>(s: *const T) -> Self { | |
| + Flow(s as usize as u64) | |
| + } | |
| +} | |
| + | |
| +impl ProfilerMarker for Flow { | |
| + fn marker_type_name() -> &'static str { | |
| + "flow" | |
| + } | |
| + | |
| + fn stream_json_marker_data(&self, json_writer: &mut JSONWriter) { | |
| + | |
| + fn hex_string(id: u64) -> [u8; 16] { | |
| + let mut buf = [0; 16]; | |
| + let hex_digits = b"0123456789abcdef"; | |
| + for i in 0..16 { | |
| + buf[i] = hex_digits[(id >> (60 - i * 4)) as usize & 0xf]; | |
| + } | |
| + buf | |
| + } | |
| + | |
| + json_writer.unique_string_property("flow", unsafe { std::str::from_utf8_unchecked(&hex_string(self.0)) }); | |
| + } | |
| + | |
| + // Tracing marker is a bit special because we have the same schema in the | |
| + // C++ side. This function will only get called when no Tracing markers are | |
| + // generated from the C++ side. But, most of the time, this will not be called | |
| + // when there is another C++ Tracing marker. | |
| + fn marker_type_display() -> MarkerSchema { | |
| + use crate::marker::schema::*; | |
| + let mut schema = MarkerSchema::new(&[ | |
| + Location::MarkerChart, | |
| + Location::MarkerTable, | |
| + Location::TimelineOverview, | |
| + ]); | |
| + schema.add_key_label_format("flow", "Type", Format::Flow); | |
| + schema.set_is_stack_based(); | |
| + schema | |
| + } | |
| +} | |
| + | |
| +/// RAII-style scoped tracing marker for Rust code. | |
| +/// This is a Rust-style equivalent of the C++ AUTO_PROFILER_TRACING_MARKER | |
| +/// Profiler markers are emitted at when an AutoProfilerFlowMarker is | |
| +/// created, and when it is dropped (destroyed). | |
| +pub struct AutoProfilerFlowMarker<'a> { | |
| + name: &'a str, | |
| + category: ProfilingCategoryPair, | |
| + options: MarkerOptions, | |
| + flow: Flow, | |
| +} | |
| + | |
| +impl<'a> AutoProfilerFlowMarker<'a> { | |
| + pub fn new( | |
| + name: &'a str, | |
| + category: ProfilingCategoryPair, | |
| + options: MarkerOptions, | |
| + flow: Flow, | |
| + ) -> Option<AutoProfilerFlowMarker<'a>> { | |
| + if !crate::profiler_state::can_accept_markers() { | |
| + return None; | |
| + } | |
| + // Record our starting marker. | |
| + add_marker( | |
| + name, | |
| + category, | |
| + options.with_timing(MarkerTiming::interval_start(ProfilerTime::now())), | |
| + flow, | |
| + ); | |
| + Some(AutoProfilerFlowMarker { | |
| + name, | |
| + category, | |
| + options, | |
| + flow, | |
| + }) | |
| + } | |
| +} | |
| + | |
| +impl<'a> Drop for AutoProfilerFlowMarker<'a> { | |
| + fn drop(&mut self) { | |
| + // If we have an AutoProfilerFlowMarker object, then the profiler was | |
| + // running + accepting markers when it was *created*. We have no | |
| + // guarantee that it's still running though, so check again! If the | |
| + // profiler has stopped, then there's no point recording the second of a | |
| + // pair of markers. | |
| + if !crate::profiler_state::can_accept_markers() { | |
| + return; | |
| + } | |
| + // record the ending marker | |
| + add_marker( | |
| + self.name, | |
| + self.category, | |
| + self.options | |
| + .with_timing(MarkerTiming::interval_end(ProfilerTime::now())), | |
| + self.flow, | |
| + ); | |
| + } | |
| +} | |
| + | |
| +/// Create an RAII-style tracing marker. See AutoProfilerFlowMarker for more | |
| +/// details. | |
| +/// | |
| +/// The arguments to this macro correspond exactly to the | |
| +/// AutoProfilerFlowMarker::new constructor. | |
| +/// | |
| +/// Example usage: | |
| +/// ```rust | |
| +/// auto_profiler_marker_tracing!( | |
| +/// "BlobRasterization", | |
| +/// gecko_profiler_category!(Graphics), | |
| +/// Default::default(), | |
| +/// "Webrender".to_string() | |
| +/// ); | |
| +/// ``` | |
| +/// | |
| +#[cfg(feature = "enabled")] | |
| +#[macro_export] | |
| +macro_rules! auto_profiler_flow_marker { | |
| + ($name:expr, $category:expr,$options:expr, $payload:expr) => { | |
| + let _macro_created_rust_tracing_marker = | |
| + $crate::AutoProfilerFlowMarker::new($name, $category, $options, $payload); | |
| + }; | |
| +} | |
| + | |
| +#[cfg(not(feature = "enabled"))] | |
| +#[macro_export] | |
| +macro_rules! auto_profiler_flow_marker { | |
| + ($name:expr, $category:expr,$options:expr, $payload:expr) => { | |
| + // Do nothing if the profiler is not enabled | |
| + }; | |
| +} | |
| diff --git a/tools/profiler/rust-api/src/marker/schema.rs b/tools/profiler/rust-api/src/marker/schema.rs | |
| index 984966e7c0821..87845a6ef6178 100644 | |
| --- a/tools/profiler/rust-api/src/marker/schema.rs | |
| +++ b/tools/profiler/rust-api/src/marker/schema.rs | |
| @@ -103,20 +103,28 @@ impl MarkerSchema { | |
| unsafe { | |
| bindings::gecko_profiler_marker_schema_set_all_labels( | |
| self.ptr, | |
| label.as_ptr() as *const c_char, | |
| label.len(), | |
| ); | |
| } | |
| self | |
| } | |
| + /// Set the marker to be stack based | |
| + pub fn set_is_stack_based(&mut self) -> &mut Self { | |
| + unsafe { | |
| + bindings::gecko_profiler_marker_schema_set_is_stack_based(self.ptr); | |
| + } | |
| + self | |
| + } | |
| + | |
| // Each data element that is streamed by `stream_json_marker_data()` can be | |
| // displayed as indicated by using one of the `add_...` function below. | |
| // Each `add...` will add a line in the full marker description. Parameters: | |
| // - `key`: Element property name as streamed by `stream_json_marker_data()`. | |
| // - `label`: Optional label. Defaults to the key name. | |
| // - `format`: How to format the data element value, see `Format` above. | |
| // - `searchable`: Optional, indicates if the value is used in searches, | |
| // defaults to false. | |
| /// Add a key / format row for the marker data element. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment