Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement --factor option #65

Merged
merged 7 commits into from
Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions src/bin/flamegraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct Opt {
/// Collapsed perf output files. With no INFILE, or INFILE is -, read STDIN.
#[structopt(name = "INFILE", parse(from_os_str))]
infiles: Vec<PathBuf>,
/// set color palette
/// Set color palette
#[structopt(
short = "c",
long = "colors",
Expand All @@ -31,23 +31,23 @@ struct Opt {
)
)]
colors: Palette,
/// set background colors. Gradient choices are yellow (default), blue, green, grey; flat colors use "#rrggbb"
/// Set background colors. Gradient choices are yellow (default), blue, green, grey; flat colors use "#rrggbb"
#[structopt(long = "bgcolors")]
bgcolors: Option<BackgroundColor>,
/// colors are keyed by function name hash
/// Colors are keyed by function name hash
#[structopt(long = "hash")]
hash: bool,
/// use consistent palette (palette.map)
/// Use consistent palette (palette.map)
#[structopt(long = "cp")]
cp: bool,

/// switch differential hues (green<->red)
/// Switch differential hues (green<->red)
#[structopt(long = "negate")]
negate: bool,

/// factor to scale sample counts by
#[structopt(long = "factor")]
factor: Option<f64>,
/// Factor to scale sample counts by
#[structopt(long = "factor", default_value = "1.0")]
factor: f64,
}

impl Into<Options> for Opt {
Expand All @@ -70,9 +70,7 @@ impl Into<Options> for Opt {
options.title = "Icicle Graph".to_string();
}
options.negate_differentials = self.negate;
if let Some(factor) = self.factor {
options.factor = factor;
}
options.factor = self.factor;
options
}
}
Expand Down
34 changes: 21 additions & 13 deletions src/flamegraph/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ where
let mut frames = Default::default();
let mut delta = None;
let mut delta_max = 1;
let mut stripped_fractional_samples = false;
for line in lines {
let mut line = line.trim();
if line.is_empty() {
Expand All @@ -124,17 +125,20 @@ where
// Usually there will only be one samples column at the end of a line,
// but for differentials there will be two. When there are two we compute the
// delta between them and use the second one.
let nsamples = if let Some(samples) = parse_nsamples(&mut line) {
// See if there's also a differential column present
if let Some(original_samples) = parse_nsamples(&mut line) {
delta = Some(samples as isize - original_samples as isize);
delta_max = std::cmp::max(delta.unwrap().abs() as usize, delta_max);
}
samples
} else {
ignored += 1;
continue;
};
let nsamples =
if let Some(samples) = parse_nsamples(&mut line, &mut stripped_fractional_samples) {
// See if there's also a differential column present
if let Some(original_samples) =
parse_nsamples(&mut line, &mut stripped_fractional_samples)
{
delta = Some(samples as isize - original_samples as isize);
delta_max = std::cmp::max(delta.unwrap().abs() as usize, delta_max);
}
samples
} else {
ignored += 1;
continue;
};

if line.is_empty() {
ignored += 1;
Expand Down Expand Up @@ -176,11 +180,15 @@ where
);
}

if stripped_fractional_samples {
warn!("The fractional parts of sample counts have been stripped. If you need to retain the extra precision you can scale up the sample data and use the --factor option to scale it back down.");
jonhoo marked this conversation as resolved.
Show resolved Hide resolved
}

(frames, time, ignored, delta_max)
}

// Parse and remove the number of samples from the end of a line.
fn parse_nsamples(line: &mut &str) -> Option<usize> {
fn parse_nsamples(line: &mut &str, stripped_fractional_samples: &mut bool) -> Option<usize> {
let samplesi = line.rfind(' ')?;
let mut samples = &line[(samplesi + 1)..];

Expand All @@ -193,7 +201,7 @@ fn parse_nsamples(line: &mut &str) -> Option<usize> {
if let Some(doti) = samples.find('.') {
// Warn if we're stripping a non-zero fractional part.
if !samples[doti + 1..].chars().all(|c| c == '0') {
warn!("Fractional part of {} stripped. If you need to retain the extra precision you can scale up the sample data and use the --factor option to scale it back down.", samples);
*stripped_fractional_samples = true;
}
samples = &samples[..doti];
}
Expand Down
6 changes: 6 additions & 0 deletions src/flamegraph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,12 @@ where
};
let rect = Rectangle { x1, y1, x2, y2 };

// The rounding here can differ from the Perl version when the fractional part is `0.5`.
// The Perl version does `my $samples = sprintf "%.0f", ($etime - $stime) * $factor;`,
// but this can format in strange ways as shown in these examples:
// `sprintf "%.0f", 1.5` produces "2"
// `sprintf "%.0f", 2.5` produces "2"
// `sprintf "%.0f", 3.5` produces "4"
let samples = ((frame.end_time - frame.start_time) as f64 * opt.factor).round() as usize;

// add thousands separators to `samples`
Expand Down