-
Notifications
You must be signed in to change notification settings - Fork 431
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
Preallocate storage for log attributes on stack #1965
Changes from 12 commits
7fee0fc
06aee01
ea7b2f8
bfb1297
fcb0ed8
40b2b5f
da8b8de
5019086
17d1628
781c3ed
b9a90c2
2bfde32
a95e681
9dc8a45
df66985
8f62fa3
fb7a44c
8611bc0
2fabca1
e52d002
92d8689
877996e
8a86be3
283816b
77e1ae1
ad42e0b
e99a957
c97a948
1adec8c
660a6d8
9e09502
8e0bfaa
9d44e26
eed39a1
9275a11
8c28428
0f6b699
1a2ec1f
adc48ca
0a4715a
b619409
6136678
1083e17
7575f4b
cb0d05d
196d2c7
c9816f0
2a149f9
3caf8b4
0a876bf
a0fc1f3
6c468e0
6f58225
b7ca124
846ca89
ee57967
f9dbdf0
8911c39
d500402
bbe5689
4117af4
b256195
40a97ac
085f001
cb200a5
da5a5ab
f3b63fb
4fa708b
e95d550
2e066fc
93b4775
e697b0d
9e8871e
e516abe
90dff08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -252,29 +252,35 @@ mod tests { | |
assert!(log.record.trace_context.is_none()); | ||
|
||
// Validate attributes | ||
let attributes: Vec<(Key, AnyValue)> = log | ||
.record | ||
.attributes | ||
.clone() | ||
.expect("Attributes are expected"); | ||
let attributes = log.record.attributes.clone(); | ||
#[cfg(not(feature = "experimental_metadata_attributes"))] | ||
assert_eq!(attributes.len(), 3); | ||
#[cfg(feature = "experimental_metadata_attributes")] | ||
assert_eq!(attributes.len(), 8); | ||
assert!(attributes.contains(&(Key::new("event_id"), 20.into()))); | ||
assert!(attributes.contains(&(Key::new("user_name"), "otel".into()))); | ||
assert!(attributes.contains(&(Key::new("user_email"), "[email protected]".into()))); | ||
assert!(attributes.contains(&Some((Key::new("event_id"), 20.into())))); | ||
assert!(attributes.contains(&Some((Key::new("user_name"), "otel".into())))); | ||
assert!(attributes.contains(&Some(( | ||
Key::new("user_email"), | ||
"[email protected]".into() | ||
)))); | ||
#[cfg(feature = "experimental_metadata_attributes")] | ||
{ | ||
assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into()))); | ||
assert!(attributes.contains(&( | ||
assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); | ||
assert!(attributes.contains(&Some(( | ||
Key::new("code.namespace"), | ||
"opentelemetry_appender_tracing::layer::tests".into() | ||
))); | ||
)))); | ||
// The other 3 experimental_metadata_attributes are too unstable to check their value. | ||
// Ex.: The path will be different on a Windows and Linux machine. | ||
// Ex.: The line can change easily if someone makes changes in this source file. | ||
let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect(); | ||
let attributes_key: Vec<Key> = attributes | ||
.iter() | ||
.filter_map(|attr| match attr { | ||
Some((key, _)) => Some(key.clone()), | ||
None => None, | ||
}) | ||
.collect(); | ||
|
||
assert!(attributes_key.contains(&Key::new("code.filepath"))); | ||
assert!(attributes_key.contains(&Key::new("code.lineno"))); | ||
assert!(attributes_key.contains(&Key::new("log.target"))); | ||
|
@@ -348,29 +354,36 @@ mod tests { | |
); | ||
|
||
// validate attributes. | ||
let attributes: Vec<(Key, AnyValue)> = log | ||
.record | ||
.attributes | ||
.clone() | ||
.expect("Attributes are expected"); | ||
let attributes = log.record.attributes.clone(); | ||
#[cfg(not(feature = "experimental_metadata_attributes"))] | ||
assert_eq!(attributes.len(), 3); | ||
#[cfg(feature = "experimental_metadata_attributes")] | ||
assert_eq!(attributes.len(), 8); | ||
assert!(attributes.contains(&(Key::new("event_id"), 20.into()))); | ||
assert!(attributes.contains(&(Key::new("user_name"), "otel".into()))); | ||
assert!(attributes.contains(&(Key::new("user_email"), "[email protected]".into()))); | ||
assert!(attributes.contains(&Some((Key::new("event_id"), 20.into())))); | ||
assert!(attributes.contains(&Some((Key::new("user_name"), "otel".into())))); | ||
assert!(attributes.contains(&Some(( | ||
Key::new("user_email"), | ||
"[email protected]".into() | ||
)))); | ||
#[cfg(feature = "experimental_metadata_attributes")] | ||
{ | ||
assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into()))); | ||
assert!(attributes.contains(&( | ||
assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); | ||
assert!(attributes.contains(&Some(( | ||
Key::new("code.namespace"), | ||
"opentelemetry_appender_tracing::layer::tests".into() | ||
))); | ||
)))); | ||
// The other 3 experimental_metadata_attributes are too unstable to check their value. | ||
// Ex.: The path will be different on a Windows and Linux machine. | ||
// Ex.: The line can change easily if someone makes changes in this source file. | ||
let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect(); | ||
|
||
//let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect(); | ||
let attributes_key: Vec<Key> = attributes | ||
.iter() | ||
.filter_map(|attr| match attr { | ||
Some((key, _)) => Some(key.clone()), | ||
None => None, | ||
}) | ||
.collect(); | ||
assert!(attributes_key.contains(&Key::new("code.filepath"))); | ||
assert!(attributes_key.contains(&Key::new("code.lineno"))); | ||
assert!(attributes_key.contains(&Key::new("log.target"))); | ||
|
@@ -415,27 +428,29 @@ mod tests { | |
|
||
// Validate attributes | ||
#[cfg(feature = "experimental_metadata_attributes")] | ||
let attributes: Vec<(Key, AnyValue)> = log | ||
.record | ||
.attributes | ||
.clone() | ||
.expect("Attributes are expected"); | ||
let attributes = log.record.attributes.clone(); | ||
|
||
// Attributes can be polluted when we don't use this feature. | ||
#[cfg(feature = "experimental_metadata_attributes")] | ||
assert_eq!(attributes.len(), 5); | ||
|
||
#[cfg(feature = "experimental_metadata_attributes")] | ||
{ | ||
assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into()))); | ||
assert!(attributes.contains(&( | ||
assert!(attributes.contains(&(Some((Key::new("code.filename"), "layer.rs".into()))))); | ||
assert!(attributes.contains(&Some(( | ||
Key::new("code.namespace"), | ||
"opentelemetry_appender_tracing::layer::tests".into() | ||
))); | ||
)))); | ||
// The other 3 experimental_metadata_attributes are too unstable to check their value. | ||
// Ex.: The path will be different on a Windows and Linux machine. | ||
// Ex.: The line can change easily if someone makes changes in this source file. | ||
let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect(); | ||
let attributes_key: Vec<Key> = attributes | ||
.iter() | ||
.filter_map(|attr| match attr { | ||
Some((key, _)) => Some(key.clone()), | ||
None => None, | ||
}) | ||
.collect(); | ||
assert!(attributes_key.contains(&Key::new("code.filepath"))); | ||
assert!(attributes_key.contains(&Key::new("code.lineno"))); | ||
assert!(attributes_key.contains(&Key::new("log.target"))); | ||
|
@@ -511,27 +526,29 @@ mod tests { | |
|
||
// validate attributes. | ||
#[cfg(feature = "experimental_metadata_attributes")] | ||
let attributes: Vec<(Key, AnyValue)> = log | ||
.record | ||
.attributes | ||
.clone() | ||
.expect("Attributes are expected"); | ||
let attributes = log.record.attributes.clone(); | ||
|
||
// Attributes can be polluted when we don't use this feature. | ||
#[cfg(feature = "experimental_metadata_attributes")] | ||
assert_eq!(attributes.len(), 5); | ||
|
||
#[cfg(feature = "experimental_metadata_attributes")] | ||
{ | ||
assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into()))); | ||
assert!(attributes.contains(&( | ||
assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); | ||
assert!(attributes.contains(&Some(( | ||
Key::new("code.namespace"), | ||
"opentelemetry_appender_tracing::layer::tests".into() | ||
))); | ||
)))); | ||
// The other 3 experimental_metadata_attributes are too unstable to check their value. | ||
// Ex.: The path will be different on a Windows and Linux machine. | ||
// Ex.: The line can change easily if someone makes changes in this source file. | ||
let attributes_key: Vec<Key> = attributes.iter().map(|(key, _)| key.clone()).collect(); | ||
let attributes_key: Vec<Key> = attributes | ||
.iter() | ||
.filter_map(|attr| match attr { | ||
Some((key, _)) => Some(key.clone()), | ||
None => None, | ||
}) | ||
.collect(); | ||
assert!(attributes_key.contains(&Key::new("code.filepath"))); | ||
assert!(attributes_key.contains(&Key::new("code.lineno"))); | ||
assert!(attributes_key.contains(&Key::new("log.target"))); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,9 @@ rustdoc-args = ["--cfg", "docsrs"] | |
[dev-dependencies] | ||
criterion = { workspace = true, features = ["html_reports"] } | ||
temp-env = { workspace = true } | ||
jemallocator = { version = "0.5"} | ||
jemalloc-ctl = { version = "0.5"} | ||
|
||
|
||
[target.'cfg(not(target_os = "windows"))'.dev-dependencies] | ||
pprof = { version = "0.13", features = ["flamegraph", "criterion"] } | ||
|
@@ -51,6 +54,9 @@ testing = ["opentelemetry/testing", "trace", "metrics", "logs", "rt-async-std", | |
rt-tokio = ["tokio", "tokio-stream"] | ||
rt-tokio-current-thread = ["tokio", "tokio-stream"] | ||
rt-async-std = ["async-std"] | ||
memory-profiling = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want this to be a crate feature? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, leftover of mem stats I though of adding earlier. Removed now. |
||
|
||
|
||
|
||
[[bench]] | ||
name = "context" | ||
|
@@ -91,3 +97,8 @@ required-features = ["metrics"] | |
name = "log" | ||
harness = false | ||
required-features = ["logs"] | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: unintentional ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes it was, removed the newline now. |
||
[[bench]] | ||
name = "growable_array" | ||
harness = false | ||
required-features = ["logs"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
use criterion::{criterion_group, criterion_main, Criterion}; | ||
use opentelemetry::logs::AnyValue; | ||
use opentelemetry::Key; | ||
use opentelemetry_sdk::logs::GrowableArray; | ||
|
||
#[derive(Clone, Debug, PartialEq)] | ||
pub struct KeyValuePair(Key, AnyValue); | ||
|
||
impl Default for KeyValuePair { | ||
fn default() -> Self { | ||
KeyValuePair(Key::from_static_str(""), AnyValue::Int(0)) | ||
} | ||
} | ||
|
||
fn growable_array_insertion_benchmark(c: &mut Criterion) { | ||
c.bench_function("GrowableArray Insertion", |b| { | ||
b.iter(|| { | ||
let mut collection = GrowableArray::<KeyValuePair>::new(); | ||
for i in 0..8 { | ||
let key = Key::from(format!("key{}", i)); | ||
let value = AnyValue::Int(i as i64); | ||
collection.push(KeyValuePair(key, value)); | ||
} | ||
}) | ||
}); | ||
} | ||
|
||
fn vec_insertion_benchmark(c: &mut Criterion) { | ||
c.bench_function("Vec Insertion", |b| { | ||
b.iter(|| { | ||
let mut collection = Vec::with_capacity(10); | ||
for i in 0..8 { | ||
let key = Key::from(format!("key{}", i)); | ||
let value = AnyValue::Int(i as i64); | ||
collection.push(KeyValuePair(key, value)); | ||
} | ||
}) | ||
}); | ||
} | ||
|
||
fn growable_array_iteration_benchmark(c: &mut Criterion) { | ||
c.bench_function("GrowableArray Iteration", |b| { | ||
let mut collection = GrowableArray::<KeyValuePair>::new(); | ||
for i in 0..8 { | ||
let key = Key::from(format!("key{}", i)); | ||
let value = AnyValue::Int(i as i64); | ||
collection.push(KeyValuePair(key, value)); | ||
} | ||
b.iter(|| { | ||
for item in &collection { | ||
criterion::black_box(item); | ||
} | ||
}) | ||
}); | ||
} | ||
|
||
fn growable_array_get_benchmark(c: &mut Criterion) { | ||
c.bench_function("GrowableArray Get Loop", |b| { | ||
let mut collection = GrowableArray::<KeyValuePair>::new(); | ||
for i in 0..8 { | ||
let key = Key::from(format!("key{}", i)); | ||
let value = AnyValue::Int(i as i64); | ||
collection.push(KeyValuePair(key, value)); | ||
} | ||
b.iter(|| { | ||
for i in 0..collection.len() { | ||
criterion::black_box(collection.get(i)); | ||
} | ||
}) | ||
}); | ||
} | ||
|
||
fn vec_iteration_benchmark(c: &mut Criterion) { | ||
c.bench_function("Vec Iteration", |b| { | ||
let mut collection = Vec::with_capacity(10); | ||
for i in 0..8 { | ||
let key = Key::from(format!("key{}", i)); | ||
let value = AnyValue::Int(i as i64); | ||
collection.push(KeyValuePair(key, value)); | ||
} | ||
b.iter(|| { | ||
for item in &collection { | ||
criterion::black_box(item); | ||
} | ||
}) | ||
}); | ||
} | ||
|
||
criterion_group!( | ||
benches, | ||
growable_array_insertion_benchmark, | ||
vec_insertion_benchmark, | ||
growable_array_iteration_benchmark, | ||
growable_array_get_benchmark, | ||
vec_iteration_benchmark | ||
); | ||
criterion_main!(benches); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this was unintended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, but it seems better now with a single newline.