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

*: support rust-protobuf #106

Merged
merged 7 commits into from Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 24 additions & 6 deletions .github/workflows/rust.yml
Expand Up @@ -25,11 +25,17 @@ jobs:
command: fmt
args: --all -- --check

- name: Run cargo clippy
- name: Run cargo clippy prost
uses: actions-rs/cargo@v1.0.3
with:
command: clippy
args: --all-features -- -D warnings
args: --features flamegraph,prost-codec -- -D warnings

- name: Run cargo clippy protobuf
uses: actions-rs/cargo@v1.0.3
with:
command: clippy
args: --features flamegraph,protobuf-codec -- -D warnings

build:
name: Build
Expand All @@ -52,11 +58,17 @@ jobs:
target: ${{ matrix.target }}
override: true

- name: Run cargo build
- name: Run cargo build prost
uses: actions-rs/cargo@v1.0.3
with:
command: build
args: --features flamegraph,prost-codec --target ${{ matrix.target }}

- name: Run cargo build protobuf
uses: actions-rs/cargo@v1.0.3
with:
command: build
args: --all-features --target ${{ matrix.target }}
args: --features flamegraph,protobuf-codec --target ${{ matrix.target }}

test:
name: Test
Expand All @@ -77,8 +89,14 @@ jobs:
toolchain: ${{ matrix.toolchain }}
override: true

- name: Run cargo test
- name: Run cargo test prost
uses: actions-rs/cargo@v1.0.3
with:
command: test
args: --features flamegraph,prost-codec

- name: Run cargo test protobuf
uses: actions-rs/cargo@v1.0.3
with:
command: test
args: --all-features
args: --features flamegraph,protobuf-codec
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -17,3 +17,5 @@ Cargo.lock
/target
#**/*.rs.bk
#Cargo.lock

.idea
7 changes: 6 additions & 1 deletion Cargo.toml
Expand Up @@ -12,7 +12,10 @@ readme = "README.md"
[features]
default = ["cpp"]
flamegraph = ["inferno"]
protobuf = ["prost", "prost-derive", "prost-build"]
# A private feature to indicate either prost-codec or protobuf-codec is enabled.
_protobuf = []
prost-codec = ["prost", "prost-derive", "prost-build", "_protobuf"]
protobuf-codec = ["protobuf", "protobuf-codegen-pure", "_protobuf"]
cpp = ["symbolic-demangle/cpp"]

[dependencies]
Expand All @@ -31,6 +34,7 @@ smallvec = "1.7"
inferno = { version = "0.10", default-features = false, features = ["nameattr"], optional = true }
prost = { version = "0.9", optional = true }
prost-derive = { version = "0.9", optional = true }
protobuf = { version = "2.0", optional = true }
criterion = {version = "0.3", optional = true}

[dependencies.symbolic-demangle]
Expand All @@ -44,6 +48,7 @@ rand = "0.8.0"

[build-dependencies]
prost-build = { version = "0.9", optional = true }
protobuf-codegen-pure = { version = "2.0", optional = true }

[[example]]
name = "flamegraph"
Expand Down
26 changes: 25 additions & 1 deletion build.rs
@@ -1,6 +1,30 @@
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

#[cfg(feature = "protobuf-codec")]
// Allow deprecated as TiKV pin versions to a outdated one.
#[allow(deprecated)]
fn generate_protobuf() {
use std::io::Write;

let out_dir = std::env::var("OUT_DIR").unwrap();
protobuf_codegen_pure::run(protobuf_codegen_pure::Args {
out_dir: &out_dir,
includes: &["proto"],
input: &["proto/profile.proto"],
customize: protobuf_codegen_pure::Customize {
generate_accessors: Some(false),
lite_runtime: Some(true),
..Default::default()
},
})
.unwrap();
let mut f = std::fs::File::create(format!("{}/mod.rs", out_dir)).unwrap();
write!(f, "pub mod profile;").unwrap();
}

fn main() {
#[cfg(feature = "protobuf")]
#[cfg(feature = "prost-codec")]
prost_build::compile_protos(&["proto/profile.proto"], &["proto/"]).unwrap();
#[cfg(feature = "protobuf-codec")]
generate_protobuf();
}
3 changes: 3 additions & 0 deletions examples/profile_proto.rs
Expand Up @@ -108,7 +108,10 @@ fn main() {
let profile = report.pprof().unwrap();

let mut content = Vec::new();
#[cfg(not(feature = "protobuf-codec"))]
profile.encode(&mut content).unwrap();
#[cfg(feature = "protobuf-codec")]
profile.write_to_vec(&mut content).unwrap();
file.write_all(&content).unwrap();

println!("report: {:?}", report);
Expand Down
3 changes: 2 additions & 1 deletion proto/profile.proto
Expand Up @@ -93,7 +93,8 @@ message Profile {

// ValueType describes the semantics and measurement units of a value.
message ValueType {
int64 type = 1; // Index into string table.
// Rename it from type to ty to avoid using keyword in Rust.
int64 ty = 1; // Index into string table.
int64 unit = 2; // Index into string table.
}

Expand Down
17 changes: 11 additions & 6 deletions src/criterion.rs
Expand Up @@ -2,14 +2,14 @@

#[cfg(feature = "flamegraph")]
use crate::flamegraph::Options as FlamegraphOptions;
#[cfg(feature = "protobuf")]
#[cfg(feature = "_protobuf")]
use crate::protos::Message;

use crate::ProfilerGuard;
use criterion::profiler::Profiler;

use std::fs::File;
#[cfg(feature = "protobuf")]
#[cfg(feature = "_protobuf")]
use std::io::Write;
use std::marker::PhantomData;
use std::os::raw::c_int;
Expand All @@ -20,7 +20,7 @@ pub enum Output<'a> {
#[cfg(feature = "flamegraph")]
Flamegraph(Option<FlamegraphOptions<'a>>),

#[cfg(feature = "protobuf")]
#[cfg(feature = "_protobuf")]
Protobuf,

#[deprecated(
Expand All @@ -45,7 +45,7 @@ impl<'a, 'b> PProfProfiler<'a, 'b> {
}
}

#[cfg(not(any(feature = "protobuf", feature = "flamegraph")))]
#[cfg(not(any(feature = "_protobuf", feature = "flamegraph")))]
compile_error!("Either feature \"protobuf\" or \"flamegraph\" must be enabled when \"criterion\" feature is enabled.");

impl<'a, 'b> Profiler for PProfProfiler<'a, 'b> {
Expand All @@ -59,7 +59,7 @@ impl<'a, 'b> Profiler for PProfProfiler<'a, 'b> {
let filename = match self.output {
#[cfg(feature = "flamegraph")]
Output::Flamegraph(_) => "flamegraph.svg",
#[cfg(feature = "protobuf")]
#[cfg(feature = "_protobuf")]
Output::Protobuf => "profile.pb",
// This is `""` but not `unreachable!()`, because `unreachable!()`
// will result in another compile error, so that the user may not
Expand All @@ -86,16 +86,21 @@ impl<'a, 'b> Profiler for PProfProfiler<'a, 'b> {
.expect("Error while writing flamegraph");
}

#[cfg(feature = "protobuf")]
#[cfg(feature = "_protobuf")]
Output::Protobuf => {
let mut output_file = output_file;

let profile = profiler.report().build().unwrap().pprof().unwrap();

let mut content = Vec::new();
#[cfg(not(feature = "protobuf-codec"))]
profile
.encode(&mut content)
.expect("Error while encoding protobuf");
#[cfg(feature = "protobuf-codec")]
profile
.write_to_vec(&mut content)
.expect("Error while encoding protobuf");

output_file
.write_all(&content)
Expand Down
11 changes: 10 additions & 1 deletion src/lib.rs
Expand Up @@ -60,12 +60,21 @@ pub use self::report::{Report, ReportBuilder};
#[cfg(feature = "flamegraph")]
pub use inferno::flamegraph;

#[cfg(feature = "protobuf")]
#[cfg(all(feature = "prost-codec", not(feature = "protobuf-codec")))]
pub mod protos {
pub use prost::Message;

include!(concat!(env!("OUT_DIR"), "/perftools.profiles.rs"));
}

#[cfg(feature = "protobuf-codec")]
pub mod protos {
pub use protobuf::Message;

include!(concat!(env!("OUT_DIR"), "/mod.rs"));

pub use self::profile::*;
}

#[cfg(feature = "criterion")]
pub mod criterion;
28 changes: 17 additions & 11 deletions src/report.rs
Expand Up @@ -209,7 +209,9 @@ mod flamegraph {
}
}

#[cfg(feature = "protobuf")]
#[cfg(feature = "_protobuf")]
#[allow(clippy::useless_conversion)]
#[allow(clippy::needless_update)]
mod protobuf {
use super::*;
use crate::protos;
Expand Down Expand Up @@ -278,10 +280,11 @@ mod protobuf {
let line = protos::Line {
function_id,
line: lineno as i64,
..protos::Line::default()
};
let loc = protos::Location {
id: function_id,
line: vec![line],
line: vec![line].into(),
..protos::Location::default()
};
// the fn_tbl has the same length with loc_tbl
Expand All @@ -302,32 +305,35 @@ mod protobuf {
*count as i64,
*count as i64 * 1_000_000_000 / self.timing.frequency as i64,
],
label: vec![thread_name],
label: vec![thread_name].into(),
..Default::default()
};
samples.push(sample);
}
let samples_value = protos::ValueType {
r#type: *strings.get(SAMPLES).unwrap() as i64,
ty: *strings.get(SAMPLES).unwrap() as i64,
unit: *strings.get(COUNT).unwrap() as i64,
..Default::default()
};
let time_value = protos::ValueType {
r#type: *strings.get(CPU).unwrap() as i64,
ty: *strings.get(CPU).unwrap() as i64,
unit: *strings.get(NANOSECONDS).unwrap() as i64,
..Default::default()
};
let profile = protos::Profile {
sample_type: vec![samples_value, time_value.clone()],
sample: samples,
string_table: str_tbl,
function: fn_tbl,
location: loc_tbl,
sample_type: vec![samples_value, time_value.clone()].into(),
sample: samples.into(),
string_table: str_tbl.into(),
function: fn_tbl.into(),
location: loc_tbl.into(),
time_nanos: self
.timing
.start_time
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_nanos() as i64,
duration_nanos: self.timing.duration.as_nanos() as i64,
period_type: Some(time_value),
period_type: Some(time_value).into(),
period: 1_000_000_000 / self.timing.frequency as i64,
..protos::Profile::default()
};
Expand Down