Begin profiling a new guest. When this function is called, the current wall-clock time is recorded as the start time for the guest. The `module_name` parameter is recorded in the profile to help identify where the profile came from. The `interval` parameter should match the rate at which you intend to call `sample`. However, this is used as a hint and not required to exactly match the real sampl
(
engine: &Engine,
module_name: &str,
interval: Duration,
modules: impl IntoIterator<Item = (String, Module)>,
)
| 108 | /// "Security" section of the [`GuestProfiler`] documentation for guidance |
| 109 | /// on what modules should not be included in this list. |
| 110 | pub fn new( |
| 111 | engine: &Engine, |
| 112 | module_name: &str, |
| 113 | interval: Duration, |
| 114 | modules: impl IntoIterator<Item = (String, Module)>, |
| 115 | ) -> Result<Self> { |
| 116 | // Check that guest debugging is not enabled. The |
| 117 | // instrumentation would make profiling results unreliable, |
| 118 | // but more fundamentally, it means that code is cloned per |
| 119 | // instantiation (for breakpoint patching) so the logic below |
| 120 | // is incorrect. |
| 121 | if engine.tunables().debug_guest { |
| 122 | crate::bail!("Profiling cannot be performed when guest-debugging is enabled."); |
| 123 | } |
| 124 | |
| 125 | let zero = ReferenceTimestamp::from_millis_since_unix_epoch(0.0); |
| 126 | let mut profile = Profile::new(module_name, zero, interval.into()); |
| 127 | |
| 128 | // Past this point, we just need to think about modules as we pull out |
| 129 | // the disparate module information from components. |
| 130 | let mut modules: Vec<_> = modules |
| 131 | .into_iter() |
| 132 | .filter_map(|(name, module)| { |
| 133 | assert!(Engine::same(module.engine(), engine)); |
| 134 | let compiled = module.compiled_module(); |
| 135 | let text_range = { |
| 136 | // Assumption: within text, the code for a given module is packed linearly and |
| 137 | // is non-overlapping; if this is violated, it should be safe but might result |
| 138 | // in incorrect profiling results. |
| 139 | let start = compiled.finished_function_ranges().next()?.1.start; |
| 140 | let end = compiled.finished_function_ranges().last()?.1.end; |
| 141 | |
| 142 | let start = (module.engine_code().text_range().start + start).raw(); |
| 143 | let end = (module.engine_code().text_range().start + end).raw(); |
| 144 | start..end |
| 145 | }; |
| 146 | |
| 147 | module_symbols(name, &module).map(|lib| { |
| 148 | let libhandle = profile.add_lib(lib); |
| 149 | ProfiledModule { |
| 150 | module, |
| 151 | fxprof_libhandle: libhandle, |
| 152 | text_range, |
| 153 | } |
| 154 | }) |
| 155 | }) |
| 156 | .collect(); |
| 157 | |
| 158 | modules.sort_unstable_by_key(|m| m.text_range.start); |
| 159 | |
| 160 | profile.set_reference_timestamp(std::time::SystemTime::now().into()); |
| 161 | let process = profile.add_process(module_name, 0, Timestamp::from_nanos_since_reference(0)); |
| 162 | let thread = profile.add_thread(process, 0, Timestamp::from_nanos_since_reference(0), true); |
| 163 | let start = Instant::now(); |
| 164 | let marker = CallMarker::new(&mut profile); |
| 165 | Ok(Self { |
| 166 | profile, |
| 167 | modules, |
nothing calls this directly
no test coverage detected