Skip to content

Commit

Permalink
Use protobuf arena to reduce memory fragments and improve performence…
Browse files Browse the repository at this point in the history
… by using a modern malloc library.
  • Loading branch information
owent committed Nov 14, 2023
1 parent 3dfcf93 commit 3e840b0
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "opentelemetry/exporters/otlp/protobuf_include_prefix.h"

#include "google/protobuf/arena.h"
#include "opentelemetry/proto/collector/logs/v1/logs_service.grpc.pb.h"
#include "opentelemetry/proto/collector/metrics/v1/metrics_service.grpc.pb.h"
#include "opentelemetry/proto/collector/trace/v1/trace_service.grpc.pb.h"
Expand Down
20 changes: 16 additions & 4 deletions exporters/otlp/src/otlp_grpc_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,26 @@ sdk::common::ExportResult OtlpGrpcExporter::Export(
return sdk::common::ExportResult::kSuccess;
}

proto::collector::trace::v1::ExportTraceServiceRequest request;
OtlpRecordableUtils::PopulateRequest(spans, &request);
google::protobuf::ArenaOptions arena_options;
// It's easy to allocate datas larger than 1024 when we populate basic resource and attributes
arena_options.initial_block_size = 1024;
// When in batch mode, it's easy to export a large number of spans at once, we can alloc a lager
// block to reduce memory fragments.
arena_options.max_block_size = 65536;
google::protobuf::Arena arena{arena_options};

proto::collector::trace::v1::ExportTraceServiceRequest *request =
google::protobuf::Arena::CreateMessage<
proto::collector::trace::v1::ExportTraceServiceRequest>(&arena);
OtlpRecordableUtils::PopulateRequest(spans, request);

auto context = OtlpGrpcClient::MakeClientContext(options_);
proto::collector::trace::v1::ExportTraceServiceResponse response;
proto::collector::trace::v1::ExportTraceServiceResponse *response =
google::protobuf::Arena::CreateMessage<
proto::collector::trace::v1::ExportTraceServiceResponse>(&arena);

grpc::Status status =
OtlpGrpcClient::DelegateExport(trace_service_stub_.get(), context.get(), request, &response);
OtlpGrpcClient::DelegateExport(trace_service_stub_.get(), context.get(), *request, response);

if (!status.ok())
{
Expand Down
20 changes: 16 additions & 4 deletions exporters/otlp/src/otlp_grpc_log_record_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,26 @@ opentelemetry::sdk::common::ExportResult OtlpGrpcLogRecordExporter::Export(
return sdk::common::ExportResult::kSuccess;
}

proto::collector::logs::v1::ExportLogsServiceRequest request;
OtlpRecordableUtils::PopulateRequest(logs, &request);
google::protobuf::ArenaOptions arena_options;
// It's easy to allocate datas larger than 1024 when we populate basic resource and attributes
arena_options.initial_block_size = 1024;
// When in batch mode, it's easy to export a large number of spans at once, we can alloc a lager
// block to reduce memory fragments.
arena_options.max_block_size = 65536;
google::protobuf::Arena arena{arena_options};

proto::collector::logs::v1::ExportLogsServiceRequest *request =
google::protobuf::Arena::CreateMessage<proto::collector::logs::v1::ExportLogsServiceRequest>(
&arena);
OtlpRecordableUtils::PopulateRequest(logs, request);

auto context = OtlpGrpcClient::MakeClientContext(options_);
proto::collector::logs::v1::ExportLogsServiceResponse response;
proto::collector::logs::v1::ExportLogsServiceResponse *response =
google::protobuf::Arena::CreateMessage<proto::collector::logs::v1::ExportLogsServiceResponse>(
&arena);

grpc::Status status =
OtlpGrpcClient::DelegateExport(log_service_stub_.get(), context.get(), request, &response);
OtlpGrpcClient::DelegateExport(log_service_stub_.get(), context.get(), *request, response);

if (!status.ok())
{
Expand Down
20 changes: 16 additions & 4 deletions exporters/otlp/src/otlp_grpc_metric_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,26 @@ opentelemetry::sdk::common::ExportResult OtlpGrpcMetricExporter::Export(
return sdk::common::ExportResult::kSuccess;
}

proto::collector::metrics::v1::ExportMetricsServiceRequest request;
OtlpMetricUtils::PopulateRequest(data, &request);
google::protobuf::ArenaOptions arena_options;
// It's easy to allocate datas larger than 1024 when we populate basic resource and attributes
arena_options.initial_block_size = 1024;
// When in batch mode, it's easy to export a large number of spans at once, we can alloc a lager
// block to reduce memory fragments.
arena_options.max_block_size = 65536;
google::protobuf::Arena arena{arena_options};

proto::collector::metrics::v1::ExportMetricsServiceRequest *request =
google::protobuf::Arena::CreateMessage<
proto::collector::metrics::v1::ExportMetricsServiceRequest>(&arena);
OtlpMetricUtils::PopulateRequest(data, request);

auto context = OtlpGrpcClient::MakeClientContext(options_);
proto::collector::metrics::v1::ExportMetricsServiceResponse response;
proto::collector::metrics::v1::ExportMetricsServiceResponse *response =
google::protobuf::Arena::CreateMessage<
proto::collector::metrics::v1::ExportMetricsServiceResponse>(&arena);

grpc::Status status = OtlpGrpcClient::DelegateExport(metrics_service_stub_.get(), context.get(),
request, &response);
*request, response);

if (!status.ok())
{
Expand Down
17 changes: 14 additions & 3 deletions exporters/otlp/src/otlp_http_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "opentelemetry/exporters/otlp/protobuf_include_prefix.h"

#include "google/protobuf/arena.h"
#include "opentelemetry/proto/collector/trace/v1/trace_service.pb.h"

#include "opentelemetry/exporters/otlp/protobuf_include_suffix.h"
Expand Down Expand Up @@ -95,12 +96,22 @@ opentelemetry::sdk::common::ExportResult OtlpHttpExporter::Export(
return opentelemetry::sdk::common::ExportResult::kSuccess;
}

proto::collector::trace::v1::ExportTraceServiceRequest service_request;
OtlpRecordableUtils::PopulateRequest(spans, &service_request);
google::protobuf::ArenaOptions arena_options;
// It's easy to allocate datas larger than 1024 when we populate basic resource and attributes
arena_options.initial_block_size = 1024;
// When in batch mode, it's easy to export a large number of spans at once, we can alloc a lager
// block to reduce memory fragments.
arena_options.max_block_size = 65536;
google::protobuf::Arena arena{arena_options};

proto::collector::trace::v1::ExportTraceServiceRequest *service_request =
google::protobuf::Arena::CreateMessage<
proto::collector::trace::v1::ExportTraceServiceRequest>(&arena);
OtlpRecordableUtils::PopulateRequest(spans, service_request);
std::size_t span_count = spans.size();
#ifdef ENABLE_ASYNC_EXPORT
http_client_->Export(
service_request, [span_count](opentelemetry::sdk::common::ExportResult result) {
*service_request, [span_count](opentelemetry::sdk::common::ExportResult result) {
if (result != opentelemetry::sdk::common::ExportResult::kSuccess)
{
OTEL_INTERNAL_LOG_ERROR("[OTLP HTTP Client] ERROR: Export "
Expand Down
18 changes: 15 additions & 3 deletions exporters/otlp/src/otlp_http_log_record_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "opentelemetry/exporters/otlp/protobuf_include_prefix.h"

#include "google/protobuf/arena.h"
#include "opentelemetry/proto/collector/logs/v1/logs_service.pb.h"

#include "opentelemetry/exporters/otlp/protobuf_include_suffix.h"
Expand Down Expand Up @@ -98,12 +99,23 @@ opentelemetry::sdk::common::ExportResult OtlpHttpLogRecordExporter::Export(
{
return opentelemetry::sdk::common::ExportResult::kSuccess;
}
proto::collector::logs::v1::ExportLogsServiceRequest service_request;
OtlpRecordableUtils::PopulateRequest(logs, &service_request);

google::protobuf::ArenaOptions arena_options;
// It's easy to allocate datas larger than 1024 when we populate basic resource and attributes
arena_options.initial_block_size = 1024;
// When in batch mode, it's easy to export a large number of spans at once, we can alloc a lager
// block to reduce memory fragments.
arena_options.max_block_size = 65536;
google::protobuf::Arena arena{arena_options};

proto::collector::logs::v1::ExportLogsServiceRequest *service_request =
google::protobuf::Arena::CreateMessage<proto::collector::logs::v1::ExportLogsServiceRequest>(
&arena);
OtlpRecordableUtils::PopulateRequest(logs, service_request);
std::size_t log_count = logs.size();
#ifdef ENABLE_ASYNC_EXPORT
http_client_->Export(
service_request, [log_count](opentelemetry::sdk::common::ExportResult result) {
*service_request, [log_count](opentelemetry::sdk::common::ExportResult result) {
if (result != opentelemetry::sdk::common::ExportResult::kSuccess)
{
OTEL_INTERNAL_LOG_ERROR("[OTLP HTTP Client] ERROR: Export "
Expand Down
20 changes: 16 additions & 4 deletions exporters/otlp/src/otlp_http_metric_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "opentelemetry/exporters/otlp/protobuf_include_prefix.h"

#include "google/protobuf/arena.h"
#include "opentelemetry/proto/collector/metrics/v1/metrics_service.pb.h"

#include "opentelemetry/exporters/otlp/protobuf_include_suffix.h"
Expand Down Expand Up @@ -101,12 +102,23 @@ opentelemetry::sdk::common::ExportResult OtlpHttpMetricExporter::Export(
{
return opentelemetry::sdk::common::ExportResult::kSuccess;
}
proto::collector::metrics::v1::ExportMetricsServiceRequest service_request;
OtlpMetricUtils::PopulateRequest(data, &service_request);

google::protobuf::ArenaOptions arena_options;
// It's easy to allocate datas larger than 1024 when we populate basic resource and attributes
arena_options.initial_block_size = 1024;
// When in batch mode, it's easy to export a large number of spans at once, we can alloc a lager
// block to reduce memory fragments.
arena_options.max_block_size = 65536;
google::protobuf::Arena arena{arena_options};

proto::collector::metrics::v1::ExportMetricsServiceRequest *service_request =
google::protobuf::Arena::CreateMessage<
proto::collector::metrics::v1::ExportMetricsServiceRequest>(&arena);
OtlpMetricUtils::PopulateRequest(data, service_request);
std::size_t metric_count = data.scope_metric_data_.size();
#ifdef ENABLE_ASYNC_EXPORT
http_client_->Export(service_request, [metric_count](
opentelemetry::sdk::common::ExportResult result) {
http_client_->Export(*service_request, [metric_count](
opentelemetry::sdk::common::ExportResult result) {
if (result != opentelemetry::sdk::common::ExportResult::kSuccess)
{
OTEL_INTERNAL_LOG_ERROR("[OTLP HTTP Client] ERROR: Export "
Expand Down

0 comments on commit 3e840b0

Please sign in to comment.