Skip to content

Commit 56e7fae

Browse files
authored
Avoid vec allocation during each export for BatchLogProcessor - Part 2 (#2488)
1 parent 9a8ad95 commit 56e7fae

File tree

2 files changed

+59
-13
lines changed

2 files changed

+59
-13
lines changed

opentelemetry-sdk/src/export/logs/mod.rs

+58-7
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,17 @@ use std::fmt::Debug;
1818
///
1919
#[derive(Debug)]
2020
pub struct LogBatch<'a> {
21-
/// The data field contains a slice of tuples, where each tuple consists of a reference to
22-
/// a `LogRecord` and a reference to an `InstrumentationScope`.
23-
data: &'a [(&'a LogRecord, &'a InstrumentationScope)],
21+
data: LogBatchData<'a>,
22+
}
23+
24+
/// The `LogBatchData` enum represents the data field of a `LogBatch`.
25+
/// It can either be:
26+
/// - A shared reference to a slice of boxed tuples, where each tuple consists of an owned `LogRecord` and an owned `InstrumentationScope`.
27+
/// - Or it can be a shared reference to a slice of tuples, where each tuple consists of a reference to a `LogRecord` and a reference to an `InstrumentationScope`.
28+
#[derive(Debug)]
29+
enum LogBatchData<'a> {
30+
BorrowedVec(&'a [Box<(LogRecord, InstrumentationScope)>]), // Used by BatchProcessor which clones the LogRecords for its own use.
31+
BorrowedSlice(&'a [(&'a LogRecord, &'a InstrumentationScope)]),
2432
}
2533

2634
impl<'a> LogBatch<'a> {
@@ -39,7 +47,17 @@ impl<'a> LogBatch<'a> {
3947
/// Note - this is not a public function, and should not be used directly. This would be
4048
/// made private in the future.
4149
pub fn new(data: &'a [(&'a LogRecord, &'a InstrumentationScope)]) -> LogBatch<'a> {
42-
LogBatch { data }
50+
LogBatch {
51+
data: LogBatchData::BorrowedSlice(data),
52+
}
53+
}
54+
55+
pub(crate) fn new_with_owned_data(
56+
data: &'a [Box<(LogRecord, InstrumentationScope)>],
57+
) -> LogBatch<'a> {
58+
LogBatch {
59+
data: LogBatchData::BorrowedVec(data),
60+
}
4361
}
4462
}
4563

@@ -54,9 +72,42 @@ impl LogBatch<'_> {
5472
/// An iterator that yields references to the `LogRecord` and `InstrumentationScope` in the batch.
5573
///
5674
pub fn iter(&self) -> impl Iterator<Item = (&LogRecord, &InstrumentationScope)> {
57-
self.data
58-
.iter()
59-
.map(|(record, library)| (*record, *library))
75+
LogBatchDataIter {
76+
data: &self.data,
77+
index: 0,
78+
}
79+
}
80+
}
81+
82+
struct LogBatchDataIter<'a> {
83+
data: &'a LogBatchData<'a>,
84+
index: usize,
85+
}
86+
87+
impl<'a> Iterator for LogBatchDataIter<'a> {
88+
type Item = (&'a LogRecord, &'a InstrumentationScope);
89+
90+
fn next(&mut self) -> Option<Self::Item> {
91+
match self.data {
92+
LogBatchData::BorrowedVec(data) => {
93+
if self.index < data.len() {
94+
let record = &*data[self.index];
95+
self.index += 1;
96+
Some((&record.0, &record.1))
97+
} else {
98+
None
99+
}
100+
}
101+
LogBatchData::BorrowedSlice(data) => {
102+
if self.index < data.len() {
103+
let record = &data[self.index];
104+
self.index += 1;
105+
Some((record.0, record.1))
106+
} else {
107+
None
108+
}
109+
}
110+
}
60111
}
61112
}
62113

opentelemetry-sdk/src/logs/log_processor.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -524,12 +524,7 @@ where
524524
return LogResult::Ok(());
525525
}
526526

527-
let log_vec: Vec<(&LogRecord, &InstrumentationScope)> = batch
528-
.iter()
529-
.map(|log_data| (&log_data.0, &log_data.1))
530-
.collect();
531-
532-
let export = exporter.export(LogBatch::new(log_vec.as_slice()));
527+
let export = exporter.export(LogBatch::new_with_owned_data(batch.as_slice()));
533528
let export_result = futures_executor::block_on(export);
534529

535530
// Clear the batch vec after exporting

0 commit comments

Comments
 (0)