Skip to content

Commit 3c04fce

Browse files
committed
Add command to compare the binary size of two arbitrary binaries
1 parent d304414 commit 3c04fce

File tree

3 files changed

+76
-18
lines changed

3 files changed

+76
-18
lines changed

collector/README.md

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -516,23 +516,28 @@ Codegen diff is currently only implemented for runtime benchmarks.
516516

517517
## Binary size statistics
518518
You can use the `binary_stats` command to display size statistics (section and symbol sizes) of
519-
binary artifacts (executables, libraries) of selected compile benchmarks.
520-
521-
```bash
522-
./target/release/collector binary_stats compile `<rustc>` --include <benchmark name> \
523-
[--profile <Debug|Opt>] \
524-
[--backend <Llvm|Cranelift>]
525-
```
526-
527-
You can also compare (diff) the size statistics between two compilers:
528-
```bash
529-
./target/release/collector binary_stats compile `<rustc>` --include <benchmark name> --rustc2 <rustc2>
530-
```
531-
or between two codegen backends:
532-
```bash
533-
./target/release/collector binary_stats compile `<rustc>` --include <benchmark name> --rustc2 <rustc>
534-
--backend <Llvm|Cranelift> --backend2 <Llvm|Cranelift>
535-
```
519+
binary artifacts (executables, libraries). You can compare the binary statistics of:
520+
521+
- Selected compile benchmarks:
522+
```bash
523+
./target/release/collector binary_stats compile `<rustc>` --include <benchmark name> \
524+
[--profile <Debug|Opt>] \
525+
[--backend <Llvm|Cranelift>]
526+
```
527+
528+
You can also compare (diff) the size statistics between two compilers:
529+
```bash
530+
./target/release/collector binary_stats compile `<rustc>` --include <benchmark name> --rustc2 <rustc2>
531+
```
532+
or between two codegen backends:
533+
```bash
534+
./target/release/collector binary_stats compile `<rustc>` --include <benchmark name> --rustc2 <rustc>
535+
--backend <Llvm|Cranelift> --backend2 <Llvm|Cranelift>
536+
```
537+
- Arbitrary binary artifacts on disk:
538+
```bash
539+
./target/release/collector binary_stats local `<artifact-path>` [<artifact-to-compare-to>]
540+
```
536541

537542
## How `rustc` wrapping works
538543
When a crate is benchmarked or profiled, the real `rustc` is replaced with the `rustc-fake` binary,

collector/src/artifact_stats.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! names and sizes.
33
44
use std::collections::{HashMap, VecDeque};
5+
use std::ffi::OsStr;
56
use std::path::{Path, PathBuf};
67
use std::process::Command;
78
use std::sync::OnceLock;
@@ -23,6 +24,17 @@ pub struct ArtifactStats {
2324
}
2425

2526
impl ArtifactStats {
27+
/// Try to auto-detect the artifact type from the given path.
28+
/// If auto-detection fails, tries to load the artifact as a dynamic object.
29+
pub fn from_path(path: &Path) -> anyhow::Result<Self> {
30+
if path.extension() == Some(OsStr::new("a")) || path.extension() == Some(OsStr::new("rlib"))
31+
{
32+
Self::from_rlib(path)
33+
} else {
34+
Self::from_dynamic_object(path)
35+
}
36+
}
37+
2638
/// Loads size statistics from an ELF file (either an executable or a shared library).
2739
pub fn from_dynamic_object(path: &Path) -> anyhow::Result<Self> {
2840
let data = std::fs::read(path)

collector/src/bin/collector.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ use tabled::settings::{Alignment, Border, Color, Modify};
2626
use tokio::runtime::Runtime;
2727

2828
use collector::api::next_artifact::NextArtifact;
29-
use collector::artifact_stats::{compile_and_get_stats, ArtifactWithStats, CargoProfile};
29+
use collector::artifact_stats::{
30+
compile_and_get_stats, ArtifactStats, ArtifactWithStats, CargoProfile,
31+
};
3032
use collector::codegen::{codegen_diff, CodegenType};
3133
use collector::compile::benchmark::category::Category;
3234
use collector::compile::benchmark::codegen_backend::CodegenBackend;
@@ -431,12 +433,25 @@ struct BinaryStatsCompile {
431433
codegen_backend2: Option<CodegenBackend>,
432434
}
433435

436+
#[derive(Debug, clap::Args)]
437+
#[command(rename_all = "snake_case")]
438+
struct BinaryStatsLocal {
439+
/// Binary artifact to examine.
440+
artifact: PathBuf,
441+
442+
/// Optional second artifact to compare with the first one.
443+
artifact2: Option<PathBuf>,
444+
}
445+
434446
#[derive(Debug, clap::Subcommand)]
435447
#[command(rename_all = "snake_case")]
436448
enum BinaryStatsMode {
437449
/// Show size statistics for the selected compile benchmark(s).
438450
/// Optionally compares sizes between two compiler toolchains, if `--rustc2` is provided.
439451
Compile(BinaryStatsCompile),
452+
/// Show size statistics for the selected binary artifact on disk.
453+
/// Optionally compares sizes with a second provided artifact, if `--artifact2` is provided.
454+
Local(BinaryStatsLocal),
440455
}
441456

442457
// For each subcommand we list the mandatory arguments in the required
@@ -667,6 +682,9 @@ fn main_result() -> anyhow::Result<i32> {
667682
BinaryStatsMode::Compile(args) => {
668683
binary_stats_compile(args, symbols, &target_triple)?;
669684
}
685+
BinaryStatsMode::Local(args) => {
686+
binary_stats_local(args, symbols)?;
687+
}
670688
}
671689

672690
Ok(0)
@@ -1168,6 +1186,29 @@ Make sure to modify `{dir}/perf-config.json` if the category/artifact don't matc
11681186
}
11691187
}
11701188

1189+
fn binary_stats_local(args: BinaryStatsLocal, symbols: bool) -> anyhow::Result<()> {
1190+
let stats = ArtifactStats::from_path(&args.artifact)
1191+
.with_context(|| format!("Cannot load artifact from {}", args.artifact.display()))?;
1192+
let stats2 = args
1193+
.artifact2
1194+
.as_ref()
1195+
.map(|path| {
1196+
ArtifactStats::from_path(&path)
1197+
.with_context(|| format!("Cannot load artifact from {}", path.display()))
1198+
})
1199+
.transpose()?;
1200+
print_binary_stats(
1201+
"Sections",
1202+
stats.sections,
1203+
stats2.as_ref().map(|s| s.sections.clone()),
1204+
);
1205+
if symbols {
1206+
print_binary_stats("Symbols", stats.symbols, stats2.map(|s| s.symbols));
1207+
}
1208+
1209+
Ok(())
1210+
}
1211+
11711212
fn binary_stats_compile(
11721213
args: BinaryStatsCompile,
11731214
symbols: bool,

0 commit comments

Comments
 (0)