Skip to content

Commit

Permalink
Add pprof feature for profiling and delete meaningless bin specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
yotarok committed Sep 21, 2023
1 parent a978830 commit fbb40e7
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 12 deletions.
15 changes: 9 additions & 6 deletions flacenc-bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,26 @@ keywords = ["flac", "lossless", "encoder", "audio"]
categories = ["compression", "multimedia::audio", "multimedia::encoding"]
repository = "https://github.com/yotarok/flacenc-rs/"

[[bin]]
name = "flacenc"
path = "src/main.rs"
default-features = []

# This is for enabling use of profilers with a release build.
[profile.release]
debug = 1


[[bin]]
name = "flacenc-exp"
name = "flacenc"
path = "src/main.rs"
default-features = ["experimental"]


[dependencies]
bitvec = "1.0.0"
clap = { version = "3.1.8", features = ["derive"] }
flacenc = { path = ".." }
hound = "3.5.0"
pprof = { version = "0.12", features = ["flamegraph", "protobuf-codec"], optional = true }
toml = "0.5"


[features]
pprof = [ "dep:pprof" ]
experimental = ["flacenc/experimental"]
56 changes: 50 additions & 6 deletions flacenc-bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ use std::path::Path;
use bitvec::prelude::BitVec;
use bitvec::prelude::Msb0;
use clap::Parser;
#[cfg(feature = "pprof")]
use pprof::protos::Message;

use flacenc::coding;
use flacenc::component::BitRepr;
Expand All @@ -79,6 +81,10 @@ struct Args {
/// If set, dump the config used to the specified path.
#[clap(long)]
dump_config: Option<String>,
/// If set, dump profiler output to the specified path.
#[cfg(feature = "pprof")]
#[clap(long)]
pprof_output: Option<String>,
}

/// Serializes `Stream` to a file.
Expand Down Expand Up @@ -154,19 +160,15 @@ fn run_encoder(
coding::encode_with_fixed_block_size(encoder_config, source, block_size)
}

#[allow(clippy::expect_used)]
#[allow(clippy::exit)]
fn main() {
let args = Args::parse();

fn main_body(args: Args) -> Result<(), i32> {
let encoder_config = args.config.map_or_else(config::Encoder::default, |path| {
let conf_str = std::fs::read_to_string(path).expect("Config file read error.");
toml::from_str(&conf_str).expect("Config file syntax error.")
});

if let Err(e) = encoder_config.verify() {
eprintln!("Error: {}", e.within("encoder_config"));
std::process::exit(ExitCode::InvalidConfig as i32);
return Err(ExitCode::InvalidConfig as i32);
}

let source = load_input_wav(&args.source).expect("Failed to load input source.");
Expand All @@ -181,4 +183,46 @@ fn main() {

let mut file = File::create(args.output).expect("Failed to create a file.");
write_stream(&stream, &mut file);
Ok(())
}

#[cfg(feature = "pprof")]
fn run_with_profiler_if_requested<F>(args: Args, body: F) -> Result<(), i32>
where
F: FnOnce(Args) -> Result<(), i32>,
{
if let Some(ref profiler_out) = args.pprof_output {
let profiler_out = profiler_out.clone();
let guard = pprof::ProfilerGuardBuilder::default()
.frequency(1000)
.blocklist(&["libc", "libgcc", "pthread", "vdso"])
.build()
.unwrap();
let result = body(args);
if let Ok(report) = guard.report().build() {
let mut file = File::create(&profiler_out).unwrap();
let profile = report.pprof().unwrap();

let mut content = Vec::new();
profile.write_to_vec(&mut content).unwrap();
file.write_all(&content).unwrap();
};
result
} else {
body(args)
}
}

#[cfg(not(feature = "pprof"))]
#[inline]
fn run_with_profiler_if_requested<F>(args: Args, body: F) -> Result<(), i32>
where
F: FnOnce(Args) -> Result<(), i32>,
{
body(args)
}

#[allow(clippy::expect_used)]
fn main() -> Result<(), i32> {
run_with_profiler_if_requested(Args::parse(), main_body)
}

0 comments on commit fbb40e7

Please sign in to comment.