Skip to content

Commit a3de32d

Browse files
committed
Move self profile result parsing from rustc-fake to collector
1 parent fe7c815 commit a3de32d

File tree

2 files changed

+117
-120
lines changed

2 files changed

+117
-120
lines changed

collector/src/bin/rustc-fake.rs

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
use anyhow::Context;
21
use std::env;
32
use std::ffi::OsString;
43
use std::fs;
5-
use std::path::Path;
64
use std::path::PathBuf;
75
use std::process::Command;
86
use std::time::{Duration, Instant};
@@ -436,55 +434,8 @@ fn process_self_profile_output(prof_out_dir: PathBuf, args: &[OsString]) {
436434
.find(|args| args[0] == "--crate-name")
437435
.and_then(|args| args[1].to_str())
438436
.expect("rustc to be invoked with crate name");
439-
let mut prefix = None;
440-
let mut full_path = None;
441-
// We don't know the pid of rustc, and can't easily get it -- we only know the
442-
// `perf` pid. So just blindly look in the directory to hopefully find it.
443-
for entry in fs::read_dir(&prof_out_dir).unwrap() {
444-
let entry = entry.unwrap();
445-
if entry
446-
.file_name()
447-
.to_str()
448-
.map_or(false, |s| s.starts_with(crate_name))
449-
{
450-
if entry.file_name().to_str().unwrap().ends_with("mm_profdata") {
451-
full_path = Some(entry.path());
452-
break;
453-
}
454-
let file = entry.file_name().to_str().unwrap().to_owned();
455-
let new_prefix = Some(file[..file.find('.').unwrap()].to_owned());
456-
assert!(
457-
prefix.is_none() || prefix == new_prefix,
458-
"prefix={:?}, new_prefix={:?}",
459-
prefix,
460-
new_prefix
461-
);
462-
prefix = new_prefix;
463-
}
464-
}
465-
if let Some(profile_data) = full_path {
466-
// measureme 0.8 has a single file
467-
println!("!self-profile-file:{}", profile_data.to_str().unwrap());
468-
let filename = profile_data.file_name().unwrap().to_str().unwrap();
469-
let json = match run_summarize("summarize", &prof_out_dir, filename) {
470-
Ok(s) => s,
471-
Err(e1) => match run_summarize("summarize-9.0", &prof_out_dir, filename) {
472-
Ok(s) => s,
473-
Err(e2) => {
474-
panic!("failed to run summarize and summarize-9.0. Errors:\nsummarize: {:?}\nsummarize-9.0: {:?}", e1, e2);
475-
}
476-
},
477-
};
478-
println!("!self-profile-output:{}", json);
479-
} else {
480-
let prefix = prefix.unwrap_or_else(|| panic!("found prefix {:?}", prof_out_dir));
481-
let json = run_summarize("summarize", &prof_out_dir, &prefix)
482-
.or_else(|_| run_summarize("summarize-0.7", &prof_out_dir, &prefix))
483-
.expect("able to run summarize or summarize-0.7");
484-
println!("!self-profile-dir:{}", prof_out_dir.to_str().unwrap());
485-
println!("!self-profile-prefix:{}", prefix);
486-
println!("!self-profile-output:{}", json);
487-
}
437+
println!("!self-profile-dir:{}", prof_out_dir.to_str().unwrap());
438+
println!("!self-profile-crate:{}", crate_name);
488439
}
489440

490441
#[cfg(windows)]
@@ -532,28 +483,5 @@ fn print_time(dur: Duration) {
532483
);
533484
}
534485

535-
fn run_summarize(name: &str, prof_out_dir: &Path, prefix: &str) -> anyhow::Result<String> {
536-
let mut cmd = Command::new(name);
537-
cmd.current_dir(prof_out_dir);
538-
cmd.arg("summarize").arg("--json");
539-
cmd.arg(prefix);
540-
let status = cmd
541-
.status()
542-
.with_context(|| format!("Command::new({}).status() failed", name))?;
543-
if !status.success() {
544-
anyhow::bail!(
545-
"failed to run {} in {:?} with prefix {:?}",
546-
name,
547-
prof_out_dir,
548-
prefix
549-
)
550-
}
551-
let json = prof_out_dir.join(format!(
552-
"{}.json",
553-
prefix.strip_suffix(".mm_profdata").unwrap_or(prefix)
554-
));
555-
fs::read_to_string(&json).with_context(|| format!("failed to read {:?}", json))
556-
}
557-
558486
#[cfg(windows)]
559487
fn print_memory() {}

collector/src/compile/execute/mod.rs

Lines changed: 115 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use std::path::{Path, PathBuf};
1919
use std::pin::Pin;
2020
use std::process::{self, Command};
2121
use std::str;
22-
use std::time::Duration;
2322

2423
pub mod bencher;
2524
mod etw_parser;
@@ -499,25 +498,15 @@ fn process_stat_output(
499498
let stdout = String::from_utf8(output.stdout.clone()).expect("utf8 output");
500499
let mut stats = Stats::new();
501500

502-
let mut profile: Option<SelfProfile> = None;
503-
let mut dir: Option<PathBuf> = None;
504-
let mut prefix: Option<String> = None;
505-
let mut file: Option<PathBuf> = None;
501+
let mut self_profile_dir: Option<PathBuf> = None;
502+
let mut self_profile_crate: Option<String> = None;
506503
for line in stdout.lines() {
507-
if let Some(stripped) = line.strip_prefix("!self-profile-output:") {
508-
profile = Some(serde_json::from_str(stripped).unwrap());
509-
continue;
510-
}
511504
if let Some(stripped) = line.strip_prefix("!self-profile-dir:") {
512-
dir = Some(PathBuf::from(stripped));
505+
self_profile_dir = Some(PathBuf::from(stripped));
513506
continue;
514507
}
515-
if let Some(stripped) = line.strip_prefix("!self-profile-prefix:") {
516-
prefix = Some(String::from(stripped));
517-
continue;
518-
}
519-
if let Some(stripped) = line.strip_prefix("!self-profile-file:") {
520-
file = Some(PathBuf::from(stripped));
508+
if let Some(stripped) = line.strip_prefix("!self-profile-crate:") {
509+
self_profile_crate = Some(String::from(stripped));
521510
continue;
522511
}
523512
if let Some(counter_file) = line.strip_prefix("!counters-file:") {
@@ -581,39 +570,13 @@ fn process_stat_output(
581570
);
582571
}
583572

584-
let files = if let (Some(prefix), Some(dir)) = (prefix, dir) {
585-
let mut string_index = PathBuf::new();
586-
let mut string_data = PathBuf::new();
587-
let mut events = PathBuf::new();
588-
for entry in fs::read_dir(&dir).unwrap() {
589-
let filename = entry.unwrap().file_name();
590-
let filename_str = filename.to_str().unwrap();
591-
let path = dir.join(filename_str);
592-
if filename_str.ends_with(".events") {
593-
assert!(filename_str.contains(&prefix), "{:?}", path);
594-
events = path;
595-
} else if filename_str.ends_with(".string_data") {
596-
assert!(filename_str.contains(&prefix), "{:?}", path);
597-
string_data = path;
598-
} else if filename_str.ends_with(".string_index") {
599-
assert!(filename_str.contains(&prefix), "{:?}", path);
600-
string_index = path;
601-
}
602-
}
603-
604-
Some(SelfProfileFiles::Seven {
605-
string_index,
606-
string_data,
607-
events,
608-
})
609-
} else {
610-
file.map(|file| SelfProfileFiles::Eight { file })
611-
};
612-
613573
if stats.is_empty() {
614574
return Err(DeserializeStatError::NoOutput(output));
615575
}
616-
576+
let (profile, files) = match (self_profile_dir, self_profile_crate) {
577+
(Some(dir), Some(krate)) => parse_self_profile(dir, krate),
578+
_ => (None, None),
579+
};
617580
Ok((stats, profile, files))
618581
}
619582

@@ -659,3 +622,109 @@ pub struct ArtifactSize {
659622
#[serde(rename = "value")]
660623
pub size: u64,
661624
}
625+
626+
fn parse_self_profile(
627+
dir: PathBuf,
628+
crate_name: String,
629+
) -> (Option<SelfProfile>, Option<SelfProfileFiles>) {
630+
// First, find the mm_profdata file prefix, or a single file containing the self-profile
631+
// results.
632+
let mut prefix = None;
633+
let mut full_path = None;
634+
// We don't know the pid of rustc, and can't easily get it -- we only know the
635+
// `perf` pid. So just blindly look in the directory to hopefully find it.
636+
for entry in fs::read_dir(&dir).unwrap() {
637+
let entry = entry.unwrap();
638+
if entry
639+
.file_name()
640+
.to_str()
641+
.map_or(false, |s| s.starts_with(&crate_name))
642+
{
643+
if entry.file_name().to_str().unwrap().ends_with("mm_profdata") {
644+
full_path = Some(entry.path());
645+
break;
646+
}
647+
let file = entry.file_name().to_str().unwrap().to_owned();
648+
let new_prefix = Some(file[..file.find('.').unwrap()].to_owned());
649+
assert!(
650+
prefix.is_none() || prefix == new_prefix,
651+
"prefix={:?}, new_prefix={:?}",
652+
prefix,
653+
new_prefix
654+
);
655+
prefix = new_prefix;
656+
}
657+
}
658+
let (profile, files) = if let Some(profile_path) = full_path {
659+
// measureme 0.8 has a single file
660+
let filename = profile_path.file_name().unwrap().to_str().unwrap();
661+
let json = run_summarize("summarize", &dir, filename)
662+
.unwrap_or_else(|e1| match run_summarize("summarize-9.0", &dir, filename) {
663+
Ok(s) => s,
664+
Err(e2) => {
665+
panic!("failed to run summarize and summarize-9.0. Errors:\nsummarize: {:?}\nsummarize-9.0: {:?}", e1, e2);
666+
}
667+
});
668+
let profile: SelfProfile = serde_json::from_str(&json).unwrap();
669+
(profile, SelfProfileFiles::Eight { file: profile_path })
670+
} else {
671+
let Some(prefix) = prefix else {
672+
return (None, None);
673+
};
674+
675+
let mut string_index = PathBuf::new();
676+
let mut string_data = PathBuf::new();
677+
let mut events = PathBuf::new();
678+
for entry in fs::read_dir(&dir).unwrap() {
679+
let filename = entry.unwrap().file_name();
680+
let filename_str = filename.to_str().unwrap();
681+
let path = dir.join(filename_str);
682+
if filename_str.ends_with(".events") {
683+
assert!(filename_str.contains(&prefix), "{:?}", path);
684+
events = path;
685+
} else if filename_str.ends_with(".string_data") {
686+
assert!(filename_str.contains(&prefix), "{:?}", path);
687+
string_data = path;
688+
} else if filename_str.ends_with(".string_index") {
689+
assert!(filename_str.contains(&prefix), "{:?}", path);
690+
string_index = path;
691+
}
692+
}
693+
694+
let files = SelfProfileFiles::Seven {
695+
string_index,
696+
string_data,
697+
events,
698+
};
699+
700+
let json = run_summarize("summarize", &dir, &prefix)
701+
.or_else(|_| run_summarize("summarize-0.7", &dir, &prefix))
702+
.expect("able to run summarize or summarize-0.7");
703+
let profile: SelfProfile = serde_json::from_str(&json).unwrap();
704+
(profile, files)
705+
};
706+
(Some(profile), Some(files))
707+
}
708+
709+
fn run_summarize(name: &str, prof_out_dir: &Path, prefix: &str) -> anyhow::Result<String> {
710+
let mut cmd = Command::new(name);
711+
cmd.current_dir(prof_out_dir);
712+
cmd.arg("summarize").arg("--json");
713+
cmd.arg(prefix);
714+
let status = cmd
715+
.status()
716+
.with_context(|| format!("Command::new({}).status() failed", name))?;
717+
if !status.success() {
718+
anyhow::bail!(
719+
"failed to run {} in {:?} with prefix {:?}",
720+
name,
721+
prof_out_dir,
722+
prefix
723+
)
724+
}
725+
let json = prof_out_dir.join(format!(
726+
"{}.json",
727+
prefix.strip_suffix(".mm_profdata").unwrap_or(prefix)
728+
));
729+
fs::read_to_string(&json).with_context(|| format!("failed to read {:?}", json))
730+
}

0 commit comments

Comments
 (0)