Skip to content

Commit

Permalink
update prost 0.11 (#166)
Browse files Browse the repository at this point in the history
Signed-off-by: Yilin Chen <sticnarf@gmail.com>

Signed-off-by: Yilin Chen <sticnarf@gmail.com>
  • Loading branch information
sticnarf committed Oct 25, 2022
1 parent a280c9e commit ada2c50
Show file tree
Hide file tree
Showing 5 changed files with 297 additions and 6 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/rust.yml
Expand Up @@ -22,19 +22,28 @@ jobs:
toolchain: stable
override: true
components: rustfmt, clippy

- name: Install protobuf compiler
run: sudo apt-get install -y protobuf-compiler

- name: Run cargo fmt
uses: actions-rs/cargo@v1.0.3
with:
command: fmt
args: --all -- --check

- name: Remove pre-generated prost files to force regeneration
run: rm proto/*.rs

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

- name: Check if the prost file committed to git is up-to-date
run: git diff --no-ext-diff --exit-code

- name: Run cargo clippy protobuf
uses: actions-rs/cargo@v1.0.3
with:
Expand Down
9 changes: 5 additions & 4 deletions Cargo.toml
Expand Up @@ -17,7 +17,7 @@ frame-pointer = []

# A private feature to indicate either prost-codec or protobuf-codec is enabled.
_protobuf = []
prost-codec = ["prost", "prost-derive", "prost-build", "_protobuf"]
prost-codec = ["prost", "prost-derive", "prost-build", "sha2", "_protobuf"]
protobuf-codec = ["protobuf", "protobuf-codegen-pure", "_protobuf"]

[dependencies]
Expand All @@ -34,8 +34,8 @@ cfg-if = "1.0"
smallvec = "1.7"

inferno = { version = "0.11", default-features = false, features = ["nameattr"], optional = true }
prost = { version = "0.10", optional = true }
prost-derive = { version = "0.10", optional = true }
prost = { version = "0.11", optional = true }
prost-derive = { version = "0.11", optional = true }
protobuf = { version = "2.0", optional = true }
criterion = {version = "0.4", optional = true}

Expand All @@ -49,7 +49,8 @@ criterion = "0.4"
rand = "0.8.0"

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

[[example]]
Expand Down
44 changes: 43 additions & 1 deletion build.rs
Expand Up @@ -22,9 +22,51 @@ fn generate_protobuf() {
write!(f, "pub mod profile;").unwrap();
}

#[cfg(feature = "prost-codec")]
fn generate_prost() {
use sha2::{Digest, Sha256};
use std::{
fmt::Write,
fs::{self, File},
io::{self, BufRead, BufReader},
};

const PRE_GENERATED_PATH: &str = "proto/perftools.profiles.rs";

// Calculate the SHA256 of the proto file
let mut hasher = Sha256::new();
let mut proto_file = BufReader::new(File::open("proto/profile.proto").unwrap());
io::copy(&mut proto_file, &mut hasher).unwrap();
let mut hex = String::new();
for b in hasher.finalize() {
write!(&mut hex, "{:x}", b).unwrap();
}
let hash_comment = format!("// {} proto/profile.proto", hex);

let first_line = File::open(PRE_GENERATED_PATH)
.and_then(|f| {
let mut reader = BufReader::new(f);
let mut first_line = String::new();
reader.read_line(&mut first_line)?;
Ok(first_line)
})
.unwrap_or_default();
// If the hash of the proto file changes, regenerate the prost file.
if first_line.trim() != hash_comment {
prost_build::Config::new()
.out_dir("proto/")
.compile_protos(&["proto/profile.proto"], &["proto/"])
.unwrap();
// Prepend the hash comment to the generated file.
let generated = fs::read_to_string(PRE_GENERATED_PATH).unwrap();
let with_hex = format!("{}\n\n{}", hash_comment, generated);
fs::write(PRE_GENERATED_PATH, with_hex).unwrap();
}
}

fn main() {
#[cfg(feature = "prost-codec")]
prost_build::compile_protos(&["proto/profile.proto"], &["proto/"]).unwrap();
generate_prost();
#[cfg(feature = "protobuf-codec")]
generate_protobuf();
}
236 changes: 236 additions & 0 deletions proto/perftools.profiles.rs
@@ -0,0 +1,236 @@
// f9f855b960d01b292a3c2642e263e6156d52631e78e0177fe51416ed5bbecc81 proto/profile.proto

#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Profile {
/// A description of the samples associated with each Sample.value.
/// For a cpu profile this might be:
/// \[["cpu","nanoseconds"]\] or \[["wall","seconds"]\] or \[["syscall","count"]\]
/// For a heap profile, this might be:
/// \[["allocations","count"\], \["space","bytes"]\],
/// If one of the values represents the number of events represented
/// by the sample, by convention it should be at index 0 and use
/// sample_type.unit == "count".
#[prost(message, repeated, tag="1")]
pub sample_type: ::prost::alloc::vec::Vec<ValueType>,
/// The set of samples recorded in this profile.
#[prost(message, repeated, tag="2")]
pub sample: ::prost::alloc::vec::Vec<Sample>,
/// Mapping from address ranges to the image/binary/library mapped
/// into that address range. mapping\[0\] will be the main binary.
#[prost(message, repeated, tag="3")]
pub mapping: ::prost::alloc::vec::Vec<Mapping>,
/// Useful program location
#[prost(message, repeated, tag="4")]
pub location: ::prost::alloc::vec::Vec<Location>,
/// Functions referenced by locations
#[prost(message, repeated, tag="5")]
pub function: ::prost::alloc::vec::Vec<Function>,
/// A common table for strings referenced by various messages.
/// string_table\[0\] must always be "".
#[prost(string, repeated, tag="6")]
pub string_table: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// frames with Function.function_name fully matching the following
/// regexp will be dropped from the samples, along with their successors.
///
/// Index into string table.
#[prost(int64, tag="7")]
pub drop_frames: i64,
/// frames with Function.function_name fully matching the following
/// regexp will be kept, even if it matches drop_functions.
///
/// Index into string table.
#[prost(int64, tag="8")]
pub keep_frames: i64,
// The following fields are informational, do not affect
// interpretation of results.

/// Time of collection (UTC) represented as nanoseconds past the epoch.
#[prost(int64, tag="9")]
pub time_nanos: i64,
/// Duration of the profile, if a duration makes sense.
#[prost(int64, tag="10")]
pub duration_nanos: i64,
/// The kind of events between sampled ocurrences.
/// e.g [ "cpu","cycles" ] or [ "heap","bytes" ]
#[prost(message, optional, tag="11")]
pub period_type: ::core::option::Option<ValueType>,
/// The number of events between sampled occurrences.
#[prost(int64, tag="12")]
pub period: i64,
/// Freeform text associated to the profile.
///
/// Indices into string table.
#[prost(int64, repeated, tag="13")]
pub comment: ::prost::alloc::vec::Vec<i64>,
/// Index into the string table of the type of the preferred sample
/// value. If unset, clients should default to the last sample value.
#[prost(int64, tag="14")]
pub default_sample_type: i64,
}
/// ValueType describes the semantics and measurement units of a value.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ValueType {
/// Rename it from type to ty to avoid using keyword in Rust.
///
/// Index into string table.
#[prost(int64, tag="1")]
pub ty: i64,
/// Index into string table.
#[prost(int64, tag="2")]
pub unit: i64,
}
/// Each Sample records values encountered in some program
/// context. The program context is typically a stack trace, perhaps
/// augmented with auxiliary information like the thread-id, some
/// indicator of a higher level request being handled etc.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Sample {
/// The ids recorded here correspond to a Profile.location.id.
/// The leaf is at location_id\[0\].
#[prost(uint64, repeated, tag="1")]
pub location_id: ::prost::alloc::vec::Vec<u64>,
/// The type and unit of each value is defined by the corresponding
/// entry in Profile.sample_type. All samples must have the same
/// number of values, the same as the length of Profile.sample_type.
/// When aggregating multiple samples into a single sample, the
/// result has a list of values that is the elemntwise sum of the
/// lists of the originals.
#[prost(int64, repeated, tag="2")]
pub value: ::prost::alloc::vec::Vec<i64>,
/// label includes additional context for this sample. It can include
/// things like a thread id, allocation size, etc
#[prost(message, repeated, tag="3")]
pub label: ::prost::alloc::vec::Vec<Label>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Label {
/// Index into string table
#[prost(int64, tag="1")]
pub key: i64,
/// At most one of the following must be present
///
/// Index into string table
#[prost(int64, tag="2")]
pub str: i64,
#[prost(int64, tag="3")]
pub num: i64,
/// Should only be present when num is present.
/// Specifies the units of num.
/// Use arbitrary string (for example, "requests") as a custom count unit.
/// If no unit is specified, consumer may apply heuristic to deduce the unit.
/// Consumers may also interpret units like "bytes" and "kilobytes" as memory
/// units and units like "seconds" and "nanoseconds" as time units,
/// and apply appropriate unit conversions to these.
///
/// Index into string table
#[prost(int64, tag="4")]
pub num_unit: i64,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Mapping {
/// Unique nonzero id for the mapping.
#[prost(uint64, tag="1")]
pub id: u64,
/// Address at which the binary (or DLL) is loaded into memory.
#[prost(uint64, tag="2")]
pub memory_start: u64,
/// The limit of the address range occupied by this mapping.
#[prost(uint64, tag="3")]
pub memory_limit: u64,
/// Offset in the binary that corresponds to the first mapped address.
#[prost(uint64, tag="4")]
pub file_offset: u64,
/// The object this entry is loaded from. This can be a filename on
/// disk for the main binary and shared libraries, or virtual
/// abstractions like "\[vdso\]".
///
/// Index into string table
#[prost(int64, tag="5")]
pub filename: i64,
/// A string that uniquely identifies a particular program version
/// with high probability. E.g., for binaries generated by GNU tools,
/// it could be the contents of the .note.gnu.build-id field.
///
/// Index into string table
#[prost(int64, tag="6")]
pub build_id: i64,
/// The following fields indicate the resolution of symbolic info.
#[prost(bool, tag="7")]
pub has_functions: bool,
#[prost(bool, tag="8")]
pub has_filenames: bool,
#[prost(bool, tag="9")]
pub has_line_numbers: bool,
#[prost(bool, tag="10")]
pub has_inline_frames: bool,
}
/// Describes function and line table debug information.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Location {
/// Unique nonzero id for the location. A profile could use
/// instruction addresses or any integer sequence as ids.
#[prost(uint64, tag="1")]
pub id: u64,
/// The id of the corresponding profile.Mapping for this location.
/// It can be unset if the mapping is unknown or not applicable for
/// this profile type.
#[prost(uint64, tag="2")]
pub mapping_id: u64,
/// The instruction address for this location, if available. It
/// should be within \[Mapping.memory_start...Mapping.memory_limit\]
/// for the corresponding mapping. A non-leaf address may be in the
/// middle of a call instruction. It is up to display tools to find
/// the beginning of the instruction if necessary.
#[prost(uint64, tag="3")]
pub address: u64,
/// Multiple line indicates this location has inlined functions,
/// where the last entry represents the caller into which the
/// preceding entries were inlined.
///
/// E.g., if memcpy() is inlined into printf:
/// line\[0\].function_name == "memcpy"
/// line\[1\].function_name == "printf"
#[prost(message, repeated, tag="4")]
pub line: ::prost::alloc::vec::Vec<Line>,
/// Provides an indication that multiple symbols map to this location's
/// address, for example due to identical code folding by the linker. In that
/// case the line information above represents one of the multiple
/// symbols. This field must be recomputed when the symbolization state of the
/// profile changes.
#[prost(bool, tag="5")]
pub is_folded: bool,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Line {
/// The id of the corresponding profile.Function for this line.
#[prost(uint64, tag="1")]
pub function_id: u64,
/// Line number in source code.
#[prost(int64, tag="2")]
pub line: i64,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Function {
/// Unique nonzero id for the function.
#[prost(uint64, tag="1")]
pub id: u64,
/// Name of the function, in human-readable form if available.
///
/// Index into string table
#[prost(int64, tag="2")]
pub name: i64,
/// Name of the function, as identified by the system.
/// For instance, it can be a C++ mangled name.
///
/// Index into string table
#[prost(int64, tag="3")]
pub system_name: i64,
/// Source file containing the function.
///
/// Index into string table
#[prost(int64, tag="4")]
pub filename: i64,
/// Line number in source file.
#[prost(int64, tag="5")]
pub start_line: i64,
}
5 changes: 4 additions & 1 deletion src/lib.rs
Expand Up @@ -70,7 +70,10 @@ pub use inferno::flamegraph;
pub mod protos {
pub use prost::Message;

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

#[cfg(feature = "protobuf-codec")]
Expand Down

0 comments on commit ada2c50

Please sign in to comment.