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

Add support for collapsing PHP Xdebug traces #253

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9073857
Rewrite stackcollapse-xdebug.php into Rust
daniellockyer Feb 7, 2019
30b6536
Prepare for multicore collapsing
daniellockyer Sep 2, 2019
174510a
Merge branch 'master' into collapse-xdebug
Jun 20, 2022
d44c761
Fix typo and three suggestions from Clippy.
Jun 20, 2022
b6b17c0
Remove irrelevant after_help information.
Jun 20, 2022
9ff782a
Clarify purpose of scale factor constant.
Jun 20, 2022
1a31666
Remove unneeded CALLS slice.
Jun 20, 2022
bb06c97
Derive Default on xdebug Folder to fix benches.
Jun 20, 2022
8bd8dc6
Reimplement for Xdebug version 3
Jun 21, 2022
8130fc9
Reduce the number of string allocations in stack gathering.
Jun 21, 2022
f578ce4
Fix correctness of stack reconstruction with multiple paths to the sa…
Jun 21, 2022
5c127cc
Tidy up and clarify some comments.
Jun 21, 2022
ce8ad4e
Tidy up parsing of stats line.
Jun 21, 2022
51cfd55
Handle multiple separate function calls correctly.
Jun 21, 2022
7c59715
Implement parsing and validating header.
Jun 21, 2022
422b2fb
Always produce occurrence, not only for leaf nodes.
Jun 21, 2022
46fdf38
Use time spent in ms as "number" of occurrences.
Jun 21, 2022
f065826
Fix tests producing temporary files that are never cleaned up.
Jun 21, 2022
4c61db6
Remove no longer used hashbrown dependency.
Jun 21, 2022
7d53ade
Remove unneeded explicit return statement.
Jun 21, 2022
c7aaf89
Fix calls registering as WithoutPath if the path was previously recor…
Jun 22, 2022
bab7d3e
Add some xdebug tests, and fix path for xdebug bench.
Jun 22, 2022
45bde9f
Add sample file for xdebug benchmark.
Jun 22, 2022
edf08a2
Fix xdebug format guessing.
Jun 22, 2022
0be09fd
Fix formatting error from merge commit.
Jun 23, 2022
0dccda7
Fix build on minimal versions of dependencies.
Jun 23, 2022
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
1,093 changes: 1,093 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ name = "inferno-collapse-guess"
path = "src/bin/collapse-guess.rs"
required-features = ["cli"]

[[bin]]
name = "inferno-collapse-xdebug"
path = "src/bin/collapse-xdebug.rs"
required-features = ["cli"]

[[bin]]
name = "inferno-flamegraph"
path = "src/bin/flamegraph.rs"
Expand Down
7 changes: 4 additions & 3 deletions benches/collapse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ use std::fs::File;
use std::io::{self, Read};

use criterion::*;
use inferno::collapse::{dtrace, perf, sample, Collapse};
use inferno::collapse::{dtrace, perf, sample, xdebug, Collapse};
use libflate::gzip::Decoder;
use once_cell::sync::Lazy;

const INFILE_DTRACE: &str = "flamegraph/example-dtrace-stacks.txt";
const INFILE_PERF: &str = "flamegraph/example-perf-stacks.txt.gz";
const INFILE_SAMPLE: &str = "tests/data/collapse-sample/large.txt.gz";
const INFILE_XDEBUG: &str = "tests/data/collapse-xdebug/xdebug.bench.xt";
const SAMPLE_SIZE: usize = 100;

static NTHREADS: Lazy<usize> = Lazy::new(num_cpus::get);
Expand Down Expand Up @@ -98,7 +99,7 @@ macro_rules! benchmark_multi {
benchmark_multi!(dtrace, "dtrace", INFILE_DTRACE);
benchmark_multi!(perf, "perf", INFILE_PERF);
benchmark_single!(sample, "sample", INFILE_SAMPLE);
benchmark_single!(xdebug, "xdebug", INFILE_XDEBUG);

criterion_group!(benches, dtrace, perf, sample);

criterion_group!(benches, dtrace, perf, sample, xdebug);
criterion_main!(benches);
75 changes: 75 additions & 0 deletions src/bin/collapse-xdebug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::io;
use std::path::PathBuf;

use clap::Parser;
use env_logger::Env;
use inferno::collapse::xdebug::{Folder, Options};
use inferno::collapse::{Collapse, DEFAULT_NTHREADS};
use once_cell::sync::Lazy;

static NTHREADS: Lazy<String> = Lazy::new(|| format!("{}", *DEFAULT_NTHREADS));

#[derive(Debug, Parser)]
#[clap(name = "inferno-collapse-xdebug")]
struct Opt {
/// Silence all log output
#[clap(short = 'q', long = "quiet")]
quiet: bool,

/// Verbose logging mode (-v, -vv, -vvv)
#[clap(short = 'v', long = "verbose", parse(from_occurrences))]
verbose: usize,

// *************** //
// *** OPTIONS *** //
// *************** //
/// Number of threads to use.
#[clap(
short = 'n',
long = "nthreads",
default_value = &NTHREADS,
value_name = "UINT"
)]
nthreads: usize,

// ************ //
// *** ARGS *** //
// ************ //
#[clap(value_name = "PATH")]
/// Xdebug script output file, or STDIN if not specified
infile: Option<PathBuf>,

#[clap(short = 'f')]
include_filenames: bool,
}

impl Opt {
fn into_parts(self) -> (Option<PathBuf>, Options) {
(
self.infile,
Options {
nthreads: self.nthreads,
include_filenames: self.include_filenames,
},
)
}
}

fn main() -> io::Result<()> {
let opt = Opt::parse();

// Initialize logger
if !opt.quiet {
env_logger::Builder::from_env(Env::default().default_filter_or(match opt.verbose {
0 => "warn",
1 => "info",
2 => "debug",
_ => "trace",
}))
.format_timestamp(None)
.init();
}

let (infile, options) = opt.into_parts();
Folder::from(options).collapse_file(infile.as_ref(), io::stdout().lock())
}
6 changes: 4 additions & 2 deletions src/collapse/guess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::io::{self, Cursor};

use log::{error, info};

use crate::collapse::{self, dtrace, perf, sample, vsprof, vtune, Collapse};
use crate::collapse::{self, dtrace, perf, sample, vsprof, vtune, xdebug, Collapse};

const LINES_PER_ITERATION: usize = 10;

Expand Down Expand Up @@ -70,10 +70,11 @@ impl Collapse for Folder {
let mut sample = sample::Folder::default();
let mut vtune = vtune::Folder::default();
let mut vsprof = vsprof::Folder::default();
let mut xdebug = xdebug::Folder::default();

// Each Collapse impl gets its own flag in this array.
// It gets set to true when the impl has been ruled out.
let mut not_applicable = [false; 5];
let mut not_applicable = [false; 6];

let mut buffer = String::new();
loop {
Expand Down Expand Up @@ -108,6 +109,7 @@ impl Collapse for Folder {
try_collapse_impl!(sample, 2);
try_collapse_impl!(vtune, 3);
try_collapse_impl!(vsprof, 4);
try_collapse_impl!(xdebug, 5);

if eof {
break;
Expand Down
7 changes: 7 additions & 0 deletions src/collapse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ pub mod vtune;
/// [crate-level documentation]: ../../index.html
pub mod vsprof;

/// Stack collapsing for the output of [`Xdebug`](https://xdebug.org/docs/execution_trace).
///
/// See the [crate-level documentation] for details.
///
/// [crate-level documentation]: ../../index.html
pub mod xdebug;

// DEFAULT_NTHREADS is public because we use it in the help text of the binaries,
// but it doesn't need to be exposed to library users, hence #[doc(hidden)].
#[doc(hidden)]
Expand Down
Loading