Skip to content

Commit 4c716fc

Browse files
committed
11.0.0: v9 format: Increase StringId and Addr size to u64
1 parent 6e3ab7d commit 4c716fc

File tree

24 files changed

+270
-71
lines changed

24 files changed

+270
-71
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [11.0.0] - 2023-12-14
4+
5+
### Changed
6+
- `measureme`: Update StringId and Addr sizes from u32 to u64 ([GH-216])
7+
- `analyzeme`: v9 file format, which uses larger events ([GH-216])
8+
39
## [10.1.2] - 2023-12-14
410

511
### Changed
@@ -232,3 +238,4 @@
232238
[GH-208]: https://github.com/rust-lang/measureme/pull/208
233239
[GH-209]: https://github.com/rust-lang/measureme/pull/209
234240
[GH-211]: https://github.com/rust-lang/measureme/pull/211
241+
[GH-216]: https://github.com/rust-lang/measureme/pull/216

analyzeme/Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "analyzeme"
3-
version = "10.1.2"
3+
version = "11.0.0"
44
authors = ["Wesley Wiser <[email protected]>", "Michael Woerister <michaelwoerister@posteo>"]
55
edition = "2018"
66
license = "MIT OR Apache-2.0"
@@ -14,7 +14,13 @@ serde = { version = "1.0", features = ["derive"] }
1414

1515
# Depending on older versions of this crate allows us to keep supporting older
1616
# file formats.
17+
18+
# File format: v7
1719
analyzeme_9_2_0 = { package = "analyzeme", git = "https://github.com/rust-lang/measureme", tag = "9.2.0" }
1820

21+
# File format: v8
22+
decodeme_10_1_2 = { package = "decodeme", git = "https://github.com/rust-lang/measureme", tag = "10.1.2" }
23+
measureme_10_1_2 = { package = "measureme", git = "https://github.com/rust-lang/measureme", tag = "10.1.2" }
24+
1925
[dev-dependencies]
2026
flate2 = "1.0"

analyzeme/src/file_formats/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ use std::fmt::Debug;
33

44
pub mod v7;
55
pub mod v8;
6+
pub mod v9;
67

7-
pub use v8 as current;
8+
pub use v9 as current;
89

910
/// The [EventDecoder] knows how to decode events for a specific file format.
1011
pub trait EventDecoder: Debug + Send + Sync {
1112
fn num_events(&self) -> usize;
12-
fn metadata(&self) -> &Metadata;
13+
fn metadata(&self) -> Metadata;
1314
fn decode_full_event<'a>(&'a self, event_index: usize) -> Event<'a>;
1415
fn decode_lightweight_event<'a>(&'a self, event_index: usize) -> LightweightEvent;
1516
}

analyzeme/src/file_formats/v7.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ impl super::EventDecoder for EventDecoder {
4141
self.legacy_profiling_data.num_events()
4242
}
4343

44-
fn metadata(&self) -> &Metadata {
45-
&self.metadata
44+
fn metadata(&self) -> Metadata {
45+
self.metadata.clone()
4646
}
4747

4848
fn decode_full_event(&self, event_index: usize) -> Event<'_> {

analyzeme/src/file_formats/v8.rs

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,84 @@
11
//! This module implements file loading for the v8 file format used until
2-
//! crate version 10.0.0
2+
//! crate version 10.0.0.
3+
//!
4+
//! The difference from v8 to v9 copes with the expansion of StringId and Addr
5+
//! types from u32 to u64. Most of the EventDecoder interface is actually
6+
//! unchanged, but the construction of "EventDecoder::new", which parses
7+
//! the stream of events, varies based on these sizes.
8+
//!
9+
//! This file provides conversions to current interfaces, relying on an
10+
//! old version of this crate to parse the u32-based v8 version.
311
4-
use crate::{Event, LightweightEvent};
5-
pub use decodeme::EventDecoder;
12+
use crate::{Event, EventPayload, LightweightEvent, Timestamp};
613
use decodeme::Metadata;
14+
use decodeme_10_1_2::event_payload::EventPayload as OldEventPayload;
15+
use decodeme_10_1_2::event_payload::Timestamp as OldTimestamp;
16+
use decodeme_10_1_2::lightweight_event::LightweightEvent as OldLightweightEvent;
17+
pub use decodeme_10_1_2::EventDecoder;
18+
use decodeme_10_1_2::Metadata as OldMetadata;
719

8-
pub const FILE_FORMAT: u32 = decodeme::CURRENT_FILE_FORMAT_VERSION;
20+
pub const FILE_FORMAT: u32 = measureme_10_1_2::file_header::CURRENT_FILE_FORMAT_VERSION;
21+
22+
// NOTE: These are functionally a hand-rolled "impl From<Old> -> New", but
23+
// given orphan rules, it seems undesirable to spread version-specific
24+
// converters around the codebase.
25+
//
26+
// In lieu of an idiomatic type conversion, we at least centralize compatibility
27+
// with the old "v8" version to this file.
28+
29+
fn v8_metadata_as_current(old: &OldMetadata) -> Metadata {
30+
Metadata {
31+
start_time: old.start_time,
32+
process_id: old.process_id,
33+
cmd: old.cmd.clone(),
34+
}
35+
}
36+
37+
fn v8_timestamp_as_current(old: OldTimestamp) -> Timestamp {
38+
match old {
39+
OldTimestamp::Interval { start, end } => Timestamp::Interval { start, end },
40+
OldTimestamp::Instant(t) => Timestamp::Instant(t),
41+
}
42+
}
43+
44+
fn v8_event_payload_as_current(old: OldEventPayload) -> EventPayload {
45+
match old {
46+
OldEventPayload::Timestamp(t) => EventPayload::Timestamp(v8_timestamp_as_current(t)),
47+
OldEventPayload::Integer(t) => EventPayload::Integer(t),
48+
}
49+
}
50+
51+
fn v8_lightweightevent_as_current(old: OldLightweightEvent) -> LightweightEvent {
52+
LightweightEvent {
53+
event_index: old.event_index,
54+
thread_id: old.thread_id,
55+
payload: v8_event_payload_as_current(old.payload),
56+
}
57+
}
958

1059
impl super::EventDecoder for EventDecoder {
1160
fn num_events(&self) -> usize {
1261
self.num_events()
1362
}
1463

15-
fn metadata(&self) -> &Metadata {
16-
self.metadata()
64+
fn metadata(&self) -> Metadata {
65+
let old = self.metadata();
66+
v8_metadata_as_current(&old)
1767
}
1868

1969
fn decode_full_event(&self, event_index: usize) -> Event<'_> {
20-
self.decode_full_event(event_index)
70+
let old = self.decode_full_event(event_index);
71+
72+
Event {
73+
event_kind: old.event_kind,
74+
label: old.label,
75+
additional_data: old.additional_data,
76+
payload: v8_event_payload_as_current(old.payload),
77+
thread_id: old.thread_id,
78+
}
2179
}
2280

2381
fn decode_lightweight_event(&self, event_index: usize) -> LightweightEvent {
24-
self.decode_lightweight_event(event_index)
82+
v8_lightweightevent_as_current(self.decode_lightweight_event(event_index))
2583
}
2684
}

analyzeme/src/file_formats/v9.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! This module implements file loading for the v9 file format
2+
3+
use crate::{Event, LightweightEvent};
4+
pub use decodeme::EventDecoder;
5+
use decodeme::Metadata;
6+
7+
pub const FILE_FORMAT: u32 = decodeme::CURRENT_FILE_FORMAT_VERSION;
8+
9+
impl super::EventDecoder for EventDecoder {
10+
fn num_events(&self) -> usize {
11+
self.num_events()
12+
}
13+
14+
fn metadata(&self) -> Metadata {
15+
self.metadata()
16+
}
17+
18+
fn decode_full_event(&self, event_index: usize) -> Event<'_> {
19+
self.decode_full_event(event_index)
20+
}
21+
22+
fn decode_lightweight_event(&self, event_index: usize) -> LightweightEvent {
23+
self.decode_lightweight_event(event_index)
24+
}
25+
}

analyzeme/src/profiling_data.rs

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use measureme::file_header::{
77
use measureme::{
88
EventId, PageTag, RawEvent, SerializationSink, SerializationSinkBuilder, StringTableBuilder,
99
};
10+
use std::cell::OnceCell;
1011
use std::fs;
1112
use std::path::Path;
1213
use std::sync::Arc;
@@ -15,6 +16,7 @@ use std::{error::Error, path::PathBuf};
1516
#[derive(Debug)]
1617
pub struct ProfilingData {
1718
event_decoder: Box<dyn EventDecoder>,
19+
metadata: OnceCell<Metadata>,
1820
}
1921

2022
impl ProfilingData {
@@ -50,9 +52,6 @@ impl ProfilingData {
5052
data: Vec<u8>,
5153
diagnostic_file_path: Option<&Path>,
5254
) -> Result<ProfilingData, Box<dyn Error + Send + Sync>> {
53-
// let event_decoder = EventDecoder::new(data, diagnostic_file_path)?;
54-
// Ok(ProfilingData { event_decoder })
55-
5655
let file_format_version = read_file_header(
5756
&data,
5857
FILE_MAGIC_TOP_LEVEL,
@@ -66,6 +65,10 @@ impl ProfilingData {
6665
data,
6766
diagnostic_file_path,
6867
)?),
68+
file_formats::v9::FILE_FORMAT => Box::new(file_formats::v9::EventDecoder::new(
69+
data,
70+
diagnostic_file_path,
71+
)?),
6972
unsupported_version => {
7073
let msg = if unsupported_version > file_formats::current::FILE_FORMAT {
7174
format!(
@@ -83,11 +86,15 @@ impl ProfilingData {
8386
}
8487
};
8588

86-
Ok(ProfilingData { event_decoder })
89+
Ok(ProfilingData {
90+
event_decoder,
91+
metadata: OnceCell::new(),
92+
})
8793
}
8894

8995
pub fn metadata(&self) -> &Metadata {
90-
self.event_decoder.metadata()
96+
// Cache the metadata during the first access
97+
self.metadata.get_or_init(|| self.event_decoder.metadata())
9198
}
9299

93100
pub fn iter<'a>(&'a self) -> ProfilerEventIterator<'a> {
@@ -301,6 +308,7 @@ impl ProfilingDataBuilder {
301308
)
302309
.unwrap(),
303310
),
311+
metadata: OnceCell::new(),
304312
}
305313
}
306314

@@ -641,6 +649,86 @@ mod tests {
641649
);
642650
}
643651

652+
// To generate this revision, a v9 revision of the rust toolchain was
653+
// created, and "rustup toolchain link" was used to name it "bespoke".
654+
// Then, the following commands were executed:
655+
//
656+
// # Make a small test binary and profile it.
657+
// cargo new --bin testbinary
658+
// cargo +bespoke rustc --bin testbinary -- -Zself-profile
659+
//
660+
// # Gzip the output profdata.
661+
// gzip testbinary-...mm_profdata
662+
// mv testbinary-...mm_profdata.gz v9.mm_profdata.gz
663+
#[test]
664+
fn can_read_v9_profdata_files() {
665+
let (data, file_format_version) =
666+
read_data_and_version("tests/profdata/v9.mm_profdata.gz");
667+
assert_eq!(file_format_version, file_formats::v9::FILE_FORMAT);
668+
let profiling_data = ProfilingData::from_paged_buffer(data, None)
669+
.expect("Creating the profiling data failed");
670+
let grouped_events = group_events(&profiling_data);
671+
let event_kinds = grouped_events
672+
.keys()
673+
.map(|k| k.as_str())
674+
.collect::<HashSet<_>>();
675+
let expect_event_kinds = vec![
676+
"GenericActivity",
677+
"IncrementalResultHashing",
678+
"Query",
679+
"ArtifactSize",
680+
]
681+
.into_iter()
682+
.collect::<HashSet<_>>();
683+
assert_eq!(event_kinds, expect_event_kinds);
684+
685+
let generic_activity_len = 5125;
686+
let incremental_hashing_len = 1844;
687+
let query_len = 1877;
688+
let artifact_size_len = 24;
689+
assert_eq!(
690+
grouped_events["GenericActivity"].len(),
691+
generic_activity_len
692+
);
693+
assert_eq!(
694+
grouped_events["IncrementalResultHashing"].len(),
695+
incremental_hashing_len
696+
);
697+
assert_eq!(grouped_events["Query"].len(), query_len);
698+
assert_eq!(grouped_events["ArtifactSize"].len(), artifact_size_len);
699+
700+
assert_eq!(
701+
grouped_events["GenericActivity"][generic_activity_len / 2].label,
702+
"metadata_decode_entry_item_attrs"
703+
);
704+
assert_eq!(
705+
grouped_events["GenericActivity"][generic_activity_len / 2].duration(),
706+
Some(Duration::from_nanos(376))
707+
);
708+
709+
assert_eq!(
710+
grouped_events["IncrementalResultHashing"][incremental_hashing_len - 1].label,
711+
"crate_hash"
712+
);
713+
assert_eq!(
714+
grouped_events["IncrementalResultHashing"][incremental_hashing_len - 1].duration(),
715+
Some(Duration::from_nanos(461))
716+
);
717+
718+
assert_eq!(grouped_events["Query"][0].label, "registered_tools");
719+
assert_eq!(
720+
grouped_events["Query"][0].duration(),
721+
Some(Duration::from_nanos(45077))
722+
);
723+
724+
assert_eq!(
725+
grouped_events["ArtifactSize"][0].label,
726+
"codegen_unit_size_estimate"
727+
);
728+
assert_eq!(grouped_events["ArtifactSize"][0].duration(), None);
729+
assert_eq!(grouped_events["ArtifactSize"][0].integer(), Some(3));
730+
}
731+
644732
fn read_data_and_version(file_path: &str) -> (Vec<u8>, u32) {
645733
let data = std::fs::read(file_path).expect("Test data not found");
646734
let mut gz = flate2::read::GzDecoder::new(&data[..]);
80.5 KB
Binary file not shown.

crox/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "crox"
3-
version = "10.1.2"
3+
version = "11.0.0"
44
authors = ["Wesley Wiser <[email protected]>"]
55
edition = "2018"
66

decodeme/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "decodeme"
3-
version = "10.1.2"
3+
version = "11.0.0"
44
edition = "2018"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

decodeme/src/lib.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ where
3838
.expect("a time that can be represented as SystemTime"))
3939
}
4040

41-
#[derive(Debug, Deserialize)]
41+
#[derive(Clone, Debug, Deserialize)]
4242
pub struct Metadata {
4343
#[serde(deserialize_with = "system_time_from_nanos")]
4444
pub start_time: SystemTime,
@@ -113,9 +113,15 @@ impl EventDecoder {
113113

114114
let mut split_data = measureme::split_streams(&entire_file_data[FILE_HEADER_SIZE..]);
115115

116-
let string_data = split_data.remove(&PageTag::StringData).expect("Invalid file: No string data found");
117-
let index_data = split_data.remove(&PageTag::StringIndex).expect("Invalid file: No string index data found");
118-
let event_data = split_data.remove(&PageTag::Events).expect("Invalid file: No event data found");
116+
let string_data = split_data
117+
.remove(&PageTag::StringData)
118+
.expect("Invalid file: No string data found");
119+
let index_data = split_data
120+
.remove(&PageTag::StringIndex)
121+
.expect("Invalid file: No string index data found");
122+
let event_data = split_data
123+
.remove(&PageTag::Events)
124+
.expect("Invalid file: No event data found");
119125

120126
Self::from_separate_buffers(string_data, index_data, event_data, diagnostic_file_path)
121127
}
@@ -151,8 +157,8 @@ impl EventDecoder {
151157
event_byte_count / RAW_EVENT_SIZE
152158
}
153159

154-
pub fn metadata(&self) -> &Metadata {
155-
&self.metadata
160+
pub fn metadata(&self) -> Metadata {
161+
self.metadata.clone()
156162
}
157163

158164
pub fn decode_full_event<'a>(&'a self, event_index: usize) -> Event<'a> {

0 commit comments

Comments
 (0)