Skip to content

Commit

Permalink
Exclude profiler (#74)
Browse files Browse the repository at this point in the history
* add initial --exclude_self option

* Add basic code to allow --exclude-self to work

* Convert PID from u32 to i32

* update cli test fixture

* Update nix deps (#73)

- `hardeningDisable` to remove the newly added
  '-fzero-call-used-regs=used-gpr' flag to clang
- fixes fornew clippy lints

* Make cargo fmt happy

* cast better

---------

Co-authored-by: Javier Honduvilla Coto <[email protected]>
  • Loading branch information
gmarler and javierhonduco authored Sep 18, 2024
1 parent 42f92f9 commit c989e3f
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ struct Cli {
help = "Derived from constant MAX_PROCESSES"
)]
mapsize_rate_limits: u32,
// Exclude myself from profiling
#[arg(long, help = "Do not profile the profiler (myself)")]
exclude_self: bool,
}

/// Exit the main thread if any thread panics. We prefer this behaviour because pretty much every
Expand Down Expand Up @@ -308,6 +311,7 @@ fn main() -> Result<(), Box<dyn Error>> {
mapsize_unwind_info_chunks: args.mapsize_unwind_info_chunks,
mapsize_unwind_tables: args.mapsize_unwind_tables,
mapsize_rate_limits: args.mapsize_rate_limits,
exclude_self: args.exclude_self,
};

let (stop_signal_sender, stop_signal_receive) = bounded(1);
Expand Down Expand Up @@ -399,8 +403,7 @@ mod tests {
cmd.assert().success();
let actual = String::from_utf8(cmd.unwrap().stdout).unwrap();
insta::assert_yaml_snapshot!(actual, @r###"
---
"Usage: lightswitch [OPTIONS]\n\nOptions:\n --pids <PIDS>\n Specific PIDs to profile\n\n --tids <TIDS>\n Specific TIDs to profile (these can be outside the PIDs selected above)\n\n --show-unwind-info <PATH_TO_BINARY>\n Show unwind info for given binary\n\n --show-info <PATH_TO_BINARY>\n Show build ID for given binary\n\n -D, --duration <DURATION>\n How long this agent will run in seconds\n \n [default: 18446744073709551615]\n\n --libbpf-logs\n Enable libbpf logs. This includes the BPF verifier output\n\n --bpf-logging\n Enable BPF programs logging\n\n --logging <LOGGING>\n Set lightswitch's logging level\n \n [default: info]\n [possible values: trace, debug, info, warn, error]\n\n --sample-freq <SAMPLE_FREQ_IN_HZ>\n Per-CPU Sampling Frequency in Hz\n \n [default: 19]\n\n --profile-format <PROFILE_FORMAT>\n Output file for Flame Graph in SVG format\n \n [default: flame-graph]\n [possible values: none, flame-graph, pprof]\n\n --profile-name <PROFILE_NAME>\n Name for the generated profile\n\n --sender <SENDER>\n Where to write the profile\n \n [default: local-disk]\n\n Possible values:\n - none: Discard the profile. Used for kernel tests\n - local-disk\n - remote\n\n --perf-buffer-bytes <PERF_BUFFER_BYTES>\n Size of each profiler perf buffer, in bytes (must be a power of 2)\n \n [default: 524288]\n\n --mapsize-info\n Print eBPF map sizes after creation\n\n --mapsize-stacks <MAPSIZE_STACKS>\n max number of individual stacks to capture before aggregation\n \n [default: 100000]\n\n --mapsize-aggregated-stacks <MAPSIZE_AGGREGATED_STACKS>\n Derived from constant MAX_AGGREGATED_STACKS_ENTRIES - max number of unique stacks after aggregation\n \n [default: 10000]\n\n --mapsize-unwind-info-chunks <MAPSIZE_UNWIND_INFO_CHUNKS>\n max number of chunks allowed inside a shard\n \n [default: 5000]\n\n --mapsize-unwind-tables <MAPSIZE_UNWIND_TABLES>\n Derived from constant MAX_UNWIND_INFO_SHARDS\n \n [default: 65]\n\n --mapsize-rate-limits <MAPSIZE_RATE_LIMITS>\n Derived from constant MAX_PROCESSES\n \n [default: 5000]\n\n -h, --help\n Print help (see a summary with '-h')\n"
"Usage: lightswitch [OPTIONS]\n\nOptions:\n --pids <PIDS>\n Specific PIDs to profile\n\n --tids <TIDS>\n Specific TIDs to profile (these can be outside the PIDs selected above)\n\n --show-unwind-info <PATH_TO_BINARY>\n Show unwind info for given binary\n\n --show-info <PATH_TO_BINARY>\n Show build ID for given binary\n\n -D, --duration <DURATION>\n How long this agent will run in seconds\n \n [default: 18446744073709551615]\n\n --libbpf-logs\n Enable libbpf logs. This includes the BPF verifier output\n\n --bpf-logging\n Enable BPF programs logging\n\n --logging <LOGGING>\n Set lightswitch's logging level\n \n [default: info]\n [possible values: trace, debug, info, warn, error]\n\n --sample-freq <SAMPLE_FREQ_IN_HZ>\n Per-CPU Sampling Frequency in Hz\n \n [default: 19]\n\n --profile-format <PROFILE_FORMAT>\n Output file for Flame Graph in SVG format\n \n [default: flame-graph]\n [possible values: none, flame-graph, pprof]\n\n --profile-name <PROFILE_NAME>\n Name for the generated profile\n\n --sender <SENDER>\n Where to write the profile\n \n [default: local-disk]\n\n Possible values:\n - none: Discard the profile. Used for kernel tests\n - local-disk\n - remote\n\n --perf-buffer-bytes <PERF_BUFFER_BYTES>\n Size of each profiler perf buffer, in bytes (must be a power of 2)\n \n [default: 524288]\n\n --mapsize-info\n Print eBPF map sizes after creation\n\n --mapsize-stacks <MAPSIZE_STACKS>\n max number of individual stacks to capture before aggregation\n \n [default: 100000]\n\n --mapsize-aggregated-stacks <MAPSIZE_AGGREGATED_STACKS>\n Derived from constant MAX_AGGREGATED_STACKS_ENTRIES - max number of unique stacks after aggregation\n \n [default: 10000]\n\n --mapsize-unwind-info-chunks <MAPSIZE_UNWIND_INFO_CHUNKS>\n max number of chunks allowed inside a shard\n \n [default: 5000]\n\n --mapsize-unwind-tables <MAPSIZE_UNWIND_TABLES>\n Derived from constant MAX_UNWIND_INFO_SHARDS\n \n [default: 65]\n\n --mapsize-rate-limits <MAPSIZE_RATE_LIMITS>\n Derived from constant MAX_PROCESSES\n \n [default: 5000]\n\n --exclude-self\n Do not profile the profiler (myself)\n\n -h, --help\n Print help (see a summary with '-h')\n"
"###);
}

Expand Down
10 changes: 10 additions & 0 deletions src/profiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ pub struct Profiler<'bpf> {
// Size of each perf buffer, in bytes
perf_buffer_bytes: usize,
session_duration: Duration,
// Whether the profiler (this process) should be excluded from profiling
exclude_self: bool,
}

// Static config
Expand Down Expand Up @@ -326,6 +328,7 @@ pub struct ProfilerConfig {
pub mapsize_unwind_info_chunks: u32,
pub mapsize_unwind_tables: u32,
pub mapsize_rate_limits: u32,
pub exclude_self: bool,
}

// Note that we normally pass in the defaults from Clap, and we don't want
Expand All @@ -346,6 +349,7 @@ impl Default for ProfilerConfig {
mapsize_unwind_info_chunks: 5000,
mapsize_unwind_tables: 65,
mapsize_rate_limits: 5000,
exclude_self: false,
}
}
}
Expand Down Expand Up @@ -398,6 +402,7 @@ impl Profiler<'_> {
.lightswitch_config
.verbose_logging
.write(profiler_config.bpf_logging);
let exclude_self = profiler_config.exclude_self;
let bpf = open_skel.load().expect("load skel");
info!("native unwinder BPF program loaded");
let native_unwinder_maps = bpf.maps();
Expand Down Expand Up @@ -491,6 +496,7 @@ impl Profiler<'_> {
sample_freq,
perf_buffer_bytes,
session_duration: Duration::from_secs(5),
exclude_self,
}
}

Expand Down Expand Up @@ -1216,6 +1222,10 @@ impl Profiler<'_> {
}

fn should_profile(&self, pid: i32) -> bool {
if self.exclude_self && pid == std::process::id() as i32 {
return false;
}

if self.filter_pids.is_empty() {
return true;
}
Expand Down

0 comments on commit c989e3f

Please sign in to comment.