diff --git a/fxprof-processed-profile/src/lib.rs b/fxprof-processed-profile/src/lib.rs index 6bfead23..796a759c 100644 --- a/fxprof-processed-profile/src/lib.rs +++ b/fxprof-processed-profile/src/lib.rs @@ -91,7 +91,7 @@ pub use profile::{ FrameHandle, FrameSymbolInfo, Profile, SamplingInterval, SourceLocation, StackHandle, StringHandle, TimelineUnit, }; -pub use reference_timestamp::ReferenceTimestamp; +pub use reference_timestamp::{PlatformSpecificReferenceTimestamp, ReferenceTimestamp}; pub use sample_table::WeightType; pub use thread::ProcessHandle; pub use timestamp::Timestamp; diff --git a/fxprof-processed-profile/src/profile.rs b/fxprof-processed-profile/src/profile.rs index dfc69589..36760ec9 100644 --- a/fxprof-processed-profile/src/profile.rs +++ b/fxprof-processed-profile/src/profile.rs @@ -31,7 +31,7 @@ use crate::sample_table::WeightType; use crate::string_table::{GlobalStringIndex, GlobalStringTable}; use crate::thread::{ProcessHandle, Thread}; use crate::timestamp::Timestamp; -use crate::{FrameFlags, Symbol}; +use crate::{FrameFlags, PlatformSpecificReferenceTimestamp, Symbol}; /// The sampling interval used during profile recording. /// @@ -181,6 +181,7 @@ pub struct Profile { pub(crate) initial_visible_threads: Vec, pub(crate) initial_selected_threads: Vec, pub(crate) reference_timestamp: ReferenceTimestamp, + pub(crate) platform_specific_reference_timestamp: Option, pub(crate) string_table: GlobalStringTable, pub(crate) marker_schemas: Vec, static_schema_marker_types: FastHashMap<&'static str, MarkerTypeHandle>, @@ -214,6 +215,7 @@ impl Profile { global_libs: GlobalLibTable::new(), kernel_libs: LibMappings::new(), reference_timestamp, + platform_specific_reference_timestamp: None, processes: Vec::new(), string_table: GlobalStringTable::new(), marker_schemas: Vec::new(), @@ -236,6 +238,14 @@ impl Profile { self.reference_timestamp = reference_timestamp; } + /// Set an additional reference timestamp with a platform-specific unit. + pub fn set_platform_specific_reference_timestamp( + &mut self, + platform_specific_reference_timestamp: PlatformSpecificReferenceTimestamp, + ) { + self.platform_specific_reference_timestamp = Some(platform_specific_reference_timestamp); + } + /// Change the product name. pub fn set_product(&mut self, product: &str) { self.product = product.to_string(); @@ -1355,6 +1365,18 @@ impl Serialize for SerializableProfileMeta<'_> { }), )?; map.serialize_entry("startTime", &self.0.reference_timestamp)?; + match &self.0.platform_specific_reference_timestamp { + Some(PlatformSpecificReferenceTimestamp::ClockMonotonicNanosecondsSinceBoot(val)) => { + map.serialize_entry("startTimeAsClockMonotonicNanosecondsSinceBoot", &val)?; + } + Some(PlatformSpecificReferenceTimestamp::MachAbsoluteTimeNanoseconds(val)) => { + map.serialize_entry("startTimeAsMachAbsoluteTimeNanoseconds", &val)?; + } + Some(PlatformSpecificReferenceTimestamp::QueryPerformanceCounterValue(val)) => { + map.serialize_entry("startTimeAsQueryPerformanceCounterValue", &val)?; + } + None => {} + } map.serialize_entry("symbolicated", &self.0.symbolicated)?; map.serialize_entry("pausedRanges", &[] as &[()])?; map.serialize_entry("version", &24)?; // this version is ignored, only "preprocessedProfileVersion" is used diff --git a/fxprof-processed-profile/src/reference_timestamp.rs b/fxprof-processed-profile/src/reference_timestamp.rs index 1850baa5..cc2080a6 100644 --- a/fxprof-processed-profile/src/reference_timestamp.rs +++ b/fxprof-processed-profile/src/reference_timestamp.rs @@ -42,3 +42,12 @@ impl Serialize for ReferenceTimestamp { self.ms_since_unix_epoch.serialize(serializer) } } + +/// An additional reference timestamp in a platform-specific unit. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub enum PlatformSpecificReferenceTimestamp { + ClockMonotonicNanosecondsSinceBoot(u64), + MachAbsoluteTimeNanoseconds(u64), + QueryPerformanceCounterValue(u64), +} diff --git a/samply/src/linux_shared/converter.rs b/samply/src/linux_shared/converter.rs index 62526002..7b308551 100644 --- a/samply/src/linux_shared/converter.rs +++ b/samply/src/linux_shared/converter.rs @@ -8,9 +8,9 @@ use debugid::DebugId; use framehop::{ExplicitModuleSectionInfo, FrameAddress, Module, Unwinder}; use fxprof_processed_profile::{ Category, CategoryColor, CategoryHandle, CpuDelta, FrameFlags, LibraryHandle, LibraryInfo, - MarkerFieldFlags, MarkerFieldFormat, MarkerTiming, Profile, ReferenceTimestamp, - SamplingInterval, StaticSchemaMarker, StaticSchemaMarkerField, StringHandle, SubcategoryHandle, - SymbolTable, ThreadHandle, + MarkerFieldFlags, MarkerFieldFormat, MarkerTiming, PlatformSpecificReferenceTimestamp, Profile, + ReferenceTimestamp, SamplingInterval, StaticSchemaMarker, StaticSchemaMarkerField, + StringHandle, SubcategoryHandle, SymbolTable, ThreadHandle, }; use linux_perf_data::linux_perf_event_reader::TaskWasPreempted; use linux_perf_data::simpleperf_dso_type::{DSO_DEX_FILE, DSO_KERNEL, DSO_KERNEL_MODULE}; @@ -164,6 +164,12 @@ where raw_to_ns_factor: 1, }; + profile.set_platform_specific_reference_timestamp( + PlatformSpecificReferenceTimestamp::ClockMonotonicNanosecondsSinceBoot( + timestamp_converter.reference_raw, + ), + ); + let cpus = if profile_creation_props.create_per_cpu_threads { let start_timestamp = timestamp_converter.convert_time(first_sample_time); Some(Cpus::new(start_timestamp, &mut profile))