Skip to content

Commit

Permalink
Update flake (#34)
Browse files Browse the repository at this point in the history
* Improve kernel tests execution with nix

Rather than the hack of hardcoding nix store hashes which worked by
sheer luck, leverage nix (the build system) to pull in the right
dependencies and produce the appropriate artifacts.

Test Plan
=========

CI + run it locally with `nix run .#vmtest`

* Update nix flakes

And add file type suffix to cargo config.

Test Plan
=========

CI
  • Loading branch information
javierhonduco authored May 29, 2024
1 parent 689a9e0 commit d6ad735
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 67 deletions.
File renamed without changes.
8 changes: 1 addition & 7 deletions .github/workflows/vmtests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,5 @@ jobs:
export DEBIAN_FRONTEND=noninteractive
sudo apt-get -y install --no-install-recommends qemu-system-x86 qemu-guest-agent
- name: Set up nix dev env
run: nix develop --command echo 0

- name: Build `lightswitch`
run: nix develop --ignore-environment --command bash -c 'cargo build'

- name: Run kernel tests
run: nix develop --command 'vmtest'
run: nix run .#vmtest
18 changes: 9 additions & 9 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 2 additions & 8 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
nativeBuildInputs = with pkgs; [
pkg-config
];
craneLib = crane.lib.${system};
craneLib = (crane.mkLib nixpkgs.legacyPackages.${system});
lightswitch = craneLib.buildPackage {
src = ./.;
doCheck = false;
Expand All @@ -64,6 +64,7 @@
];
};
};
vmtest = (import ./vm.nix { inherit pkgs; }).run-vmtest lightswitch;
};
devShells.default = mkShell {
nativeBuildInputs = nativeBuildInputs;
Expand All @@ -79,13 +80,6 @@
# snapshot testing plugin binary
cargo-insta
# ocamlPackages.magic-trace
(import ./vm.nix { inherit pkgs; }).vmtest
(import ./vm.nix { inherit pkgs; }).kernel_5_15
(import ./vm.nix { inherit pkgs; }).kernel_6_0
(import ./vm.nix { inherit pkgs; }).kernel_6_2
(import ./vm.nix { inherit pkgs; }).kernel_6_6
(import ./vm.nix { inherit pkgs; }).kernel_6_8_7
(import ./vm.nix { inherit pkgs; }).kernel_6_9_rc5
];

LIBCLANG_PATH = lib.makeLibraryPath [ llvmPackages_16.libclang ];
Expand Down
44 changes: 31 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ enum LoggingLevel {
Error,
}

#[derive(clap::ValueEnum, Debug, Clone, Default)]
enum ProfileFormat {
#[default]
FlameGraph,
/// Do not produce a profile. Used for kernel tests.
None,
}

#[derive(Parser, Debug)]
struct Cli {
/// Specific PIDs to profile
Expand All @@ -93,13 +101,13 @@ struct Cli {
tids: Vec<i32>,
/// Show unwind info for given binary
#[arg(long, value_name = "PATH_TO_BINARY",
conflicts_with_all = ["pids", "tids", "show_info", "duration", "sample_freq", "flamegraph_file"]
conflicts_with_all = ["pids", "tids", "show_info", "duration", "sample_freq", "profile_name"]
)]
show_unwind_info: Option<String>,
/// Show build ID for given binary
#[arg(long, value_name = "PATH_TO_BINARY",
conflicts_with_all = ["pids", "tids", "duration",
"sample_freq", "flamegraph_file"]
"sample_freq", "profile_name"]
)]
show_info: Option<String>,
/// How long this agent will run in seconds
Expand All @@ -123,8 +131,12 @@ struct Cli {
)]
sample_freq: u16,
/// Output file for Flame Graph in SVG format
#[arg(long, default_value_t, value_enum)]
profile_format: ProfileFormat,
/// Name for the generated profile.
// TODO: change suffix depending on the format.
#[arg(long, default_value = "flame.svg")]
flamegraph_file: PathBuf,
profile_name: PathBuf,
}

/// Exit the main thread if any thread panics. We prefer this behaviour because pretty much every
Expand Down Expand Up @@ -297,16 +309,22 @@ fn main() -> Result<(), Box<dyn Error>> {
}
}

let mut options: flamegraph::Options<'_> = flamegraph::Options::default();
let data = folded.as_bytes();
let flame_path = args.flamegraph_file;
let f = File::create(flame_path).unwrap();
match flamegraph::from_reader(&mut options, data, f) {
Ok(_) => {
eprintln!("Profile successfully written to disk");
match args.profile_format {
ProfileFormat::FlameGraph => {
let mut options: flamegraph::Options<'_> = flamegraph::Options::default();
let data = folded.as_bytes();
let f = File::create(args.profile_name).unwrap();
match flamegraph::from_reader(&mut options, data, f) {
Ok(_) => {
eprintln!("Profile successfully written to disk");
}
Err(e) => {
error!("Failed generate profile: {:?}", e);
}
}
}
Err(e) => {
error!("Failed generate profile: {:?}", e);
ProfileFormat::None => {
// Do nothing
}
}

Expand Down Expand Up @@ -335,7 +353,7 @@ mod tests {
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 --tids <TIDS>\n Specific TIDs to profile (these can be outside the PIDs selected above)\n --show-unwind-info <PATH_TO_BINARY>\n Show unwind info for given binary\n --show-info <PATH_TO_BINARY>\n Show build ID for given binary\n -D, --duration <DURATION>\n How long this agent will run in seconds [default: 18446744073709551615]\n --libbpf-logs\n Enable libbpf logs. This includes the BPF verifier output\n --bpf-logging\n Enable BPF programs logging\n --logging <LOGGING>\n Set lightswitch's logging level [default: info] [possible values: trace, debug, info, warn, error]\n --sample-freq <SAMPLE_FREQ_IN_HZ>\n Per-CPU Sampling Frequency in Hz [default: 19]\n --flamegraph-file <FLAMEGRAPH_FILE>\n Output file for Flame Graph in SVG format [default: flame.svg]\n -h, --help\n Print help\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\n Possible values:\n - flame-graph\n - none: Do not produce a profile. Used for kernel tests\n\n --profile-name <PROFILE_NAME>\n Name for the generated profile\n \n [default: flame.svg]\n\n -h, --help\n Print help (see a summary with '-h')\n"
"###);
}

Expand Down
51 changes: 50 additions & 1 deletion vm.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{ pkgs }:
{
let

kernel_5_15 = pkgs.stdenv.mkDerivation {
name = "download-kernel-5.15";
src = pkgs.fetchurl {
Expand Down Expand Up @@ -78,6 +79,48 @@
'';
};

vmtest-create-config = lightswitch: pkgs.stdenv.mkDerivation {
name = "vmtest-dump-config";
dontUnpack = true;

src = pkgs.writeText "vmtest.toml" ''
[[target]]
name = "Fedora 5.15"
kernel = "${kernel_5_15}/bzImage"
command = "${lightswitch}/bin/lightswitch --duration 0 --profile-format=none"
[[target]]
name = "Fedora 6.0"
kernel = "${kernel_6_0}/bzImage"
command = "${lightswitch}/bin/lightswitch --duration 0 --profile-format=none"
[[target]]
name = "Fedora 6.2"
kernel = "${kernel_6_2}/bzImage"
command = "${lightswitch}/bin/lightswitch --duration 0 --profile-format=none"
[[target]]
name = "Fedora 6.6"
kernel = "${kernel_6_6}/bzImage"
command = "${lightswitch}/bin/lightswitch --duration 0 --profile-format=none"
[[target]]
name = "Upstream 6.8.7"
kernel = "${kernel_6_8_7}/bzImage"
command = "${lightswitch}/bin/lightswitch --duration 0 --profile-format=none"
[[target]]
name = "Upstream v6.9-rc5"
kernel = "${kernel_6_9_rc5}/bzImage"
command = "${lightswitch}/bin/lightswitch --duration 0 --profile-format=none"
'';
nativeBuildInputs = [ ];
installPhase = ''
mkdir -p $out
cp -r $src $out/vmtest.toml
'';
};

vmtest = pkgs.rustPlatform.buildRustPackage {
name = "vmtest";
src = pkgs.fetchFromGitHub {
Expand All @@ -101,4 +144,10 @@
platforms = platforms.linux;
};
};
in
{
run-vmtest = lightswitch:
pkgs.writeShellScriptBin "run-vmtests" ''
${vmtest}/bin/vmtest --config ${vmtest-create-config lightswitch}/vmtest.toml
'';
}
29 changes: 0 additions & 29 deletions vmtest.toml

This file was deleted.

0 comments on commit d6ad735

Please sign in to comment.