Skip to content

Commit

Permalink
Avoid vec allocation during each export for BatchLogProcessor - Part 2 (
Browse files Browse the repository at this point in the history
  • Loading branch information
utpilla authored Dec 31, 2024
1 parent 9a8ad95 commit 56e7fae
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 13 deletions.
65 changes: 58 additions & 7 deletions opentelemetry-sdk/src/export/logs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,17 @@ use std::fmt::Debug;
///
#[derive(Debug)]
pub struct LogBatch<'a> {
/// The data field contains a slice of tuples, where each tuple consists of a reference to
/// a `LogRecord` and a reference to an `InstrumentationScope`.
data: &'a [(&'a LogRecord, &'a InstrumentationScope)],
data: LogBatchData<'a>,
}

/// The `LogBatchData` enum represents the data field of a `LogBatch`.
/// It can either be:
/// - A shared reference to a slice of boxed tuples, where each tuple consists of an owned `LogRecord` and an owned `InstrumentationScope`.
/// - 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`.
#[derive(Debug)]
enum LogBatchData<'a> {
BorrowedVec(&'a [Box<(LogRecord, InstrumentationScope)>]), // Used by BatchProcessor which clones the LogRecords for its own use.
BorrowedSlice(&'a [(&'a LogRecord, &'a InstrumentationScope)]),
}

impl<'a> LogBatch<'a> {
Expand All @@ -39,7 +47,17 @@ impl<'a> LogBatch<'a> {
/// Note - this is not a public function, and should not be used directly. This would be
/// made private in the future.
pub fn new(data: &'a [(&'a LogRecord, &'a InstrumentationScope)]) -> LogBatch<'a> {
LogBatch { data }
LogBatch {
data: LogBatchData::BorrowedSlice(data),
}
}

pub(crate) fn new_with_owned_data(
data: &'a [Box<(LogRecord, InstrumentationScope)>],
) -> LogBatch<'a> {
LogBatch {
data: LogBatchData::BorrowedVec(data),
}
}
}

Expand All @@ -54,9 +72,42 @@ impl LogBatch<'_> {
/// An iterator that yields references to the `LogRecord` and `InstrumentationScope` in the batch.
///
pub fn iter(&self) -> impl Iterator<Item = (&LogRecord, &InstrumentationScope)> {
self.data
.iter()
.map(|(record, library)| (*record, *library))
LogBatchDataIter {
data: &self.data,
index: 0,
}
}
}

struct LogBatchDataIter<'a> {
data: &'a LogBatchData<'a>,
index: usize,
}

impl<'a> Iterator for LogBatchDataIter<'a> {
type Item = (&'a LogRecord, &'a InstrumentationScope);

fn next(&mut self) -> Option<Self::Item> {
match self.data {
LogBatchData::BorrowedVec(data) => {
if self.index < data.len() {
let record = &*data[self.index];
self.index += 1;
Some((&record.0, &record.1))
} else {
None
}
}
LogBatchData::BorrowedSlice(data) => {
if self.index < data.len() {
let record = &data[self.index];
self.index += 1;
Some((record.0, record.1))
} else {
None
}
}
}
}
}

Expand Down
7 changes: 1 addition & 6 deletions opentelemetry-sdk/src/logs/log_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,12 +524,7 @@ where
return LogResult::Ok(());
}

let log_vec: Vec<(&LogRecord, &InstrumentationScope)> = batch
.iter()
.map(|log_data| (&log_data.0, &log_data.1))
.collect();

let export = exporter.export(LogBatch::new(log_vec.as_slice()));
let export = exporter.export(LogBatch::new_with_owned_data(batch.as_slice()));
let export_result = futures_executor::block_on(export);

// Clear the batch vec after exporting
Expand Down

0 comments on commit 56e7fae

Please sign in to comment.