|
|
|
#include <algorithm>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <memory>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <benchmark/benchmark.h>
|
|
|
|
#include "absl/log/absl_check.h"
|
|
|
|
#include "google/protobuf/repeated_ptr_field.h"
|
|
|
|
#include "google/protobuf/rust/test/benchmarks/bench_data.pb.h"
|
|
|
|
#include "google/protobuf/rust/test/benchmarks/bench_data.upb.proto.h"
|
|
|
|
#include "protos/protos.h"
|
|
|
|
|
|
|
|
using benchmarks::BenchData;
|
|
|
|
|
|
|
|
#ifdef BENCHMARK_UPB
|
|
|
|
#define PROTO_BENCHMARK(NAME) EXTERN_BENCHMARK(NAME##_upb);
|
|
|
|
#else
|
|
|
|
#define PROTO_BENCHMARK(NAME) EXTERN_BENCHMARK(NAME##_cpp);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define EXTERN_BENCHMARK(NAME) \
|
|
|
|
extern "C" { \
|
|
|
|
void NAME##_bench(); \
|
|
|
|
} \
|
|
|
|
void BM_##NAME(benchmark::State& state) { \
|
|
|
|
for (auto s : state) { \
|
|
|
|
NAME##_bench(); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
BENCHMARK(BM_##NAME);
|
|
|
|
|
|
|
|
void BM_set_string_cpp(benchmark::State& state) {
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = std::make_unique<BenchData>();
|
|
|
|
data->set_name(
|
|
|
|
"a relatively long string that will avoid any short string "
|
|
|
|
"optimizations.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_set_string_cpp);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(set_string_rs);
|
|
|
|
|
|
|
|
void BM_set_int_cpp(benchmark::State& state) {
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = std::make_unique<BenchData>();
|
|
|
|
data->set_num2(123456789);
|
|
|
|
ABSL_CHECK_EQ(data->num2(), 123456789);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_set_int_cpp);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(set_int_rs);
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
void benchmark_thunk_set_num2_rs(void* data, int32_t num2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BM_set_int_cpp_roundtrip(benchmark::State& state) {
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = std::make_unique<BenchData>();
|
|
|
|
benchmark_thunk_set_num2_rs((void*)data.get(), 123456789);
|
|
|
|
ABSL_CHECK_EQ(data->num2(), 123456789);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_set_int_cpp_roundtrip);
|
|
|
|
|
|
|
|
void BM_add_10_repeated_msg_copy_cpp(benchmark::State& state) {
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = std::make_unique<BenchData>();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
auto sub_data = std::make_unique<BenchData>();
|
|
|
|
sub_data->set_num2(i);
|
|
|
|
*data->add_subs() = *sub_data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_add_10_repeated_msg_copy_cpp);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(add_10_repeated_msg_rs);
|
|
|
|
|
|
|
|
void BM_add_10_repeated_msg_direct_cpp(benchmark::State& state) {
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = std::make_unique<BenchData>();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
auto sub_data = data->add_subs();
|
|
|
|
sub_data->set_num2(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_add_10_repeated_msg_direct_cpp);
|
|
|
|
|
|
|
|
void BM_copy_from_10_repeated_msg_cpp(benchmark::State& state) {
|
|
|
|
auto source = std::make_unique<BenchData>();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
auto sub_data = source->add_subs();
|
|
|
|
sub_data->set_num2(i);
|
|
|
|
}
|
|
|
|
for (auto s : state) {
|
|
|
|
benchmarks::BenchData data;
|
|
|
|
*data.mutable_subs() = source->subs();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_copy_from_10_repeated_msg_cpp);
|
|
|
|
|
|
|
|
void BM_back_inserter_from_10_repeated_msg_cpp(benchmark::State& state) {
|
|
|
|
auto source = std::make_unique<BenchData>();
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
auto sub_data = source->add_subs();
|
|
|
|
sub_data->set_num2(i);
|
|
|
|
}
|
|
|
|
for (auto s : state) {
|
|
|
|
benchmarks::BenchData data;
|
|
|
|
std::copy(source->subs().begin(), source->subs().end(),
|
|
|
|
google::protobuf::RepeatedFieldBackInserter(data.mutable_subs()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_back_inserter_from_10_repeated_msg_cpp);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(copy_from_10_repeated_msg_rs);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(extend_10_repeated_msg_rs);
|
|
|
|
|
|
|
|
void BM_add_100_ints_cpp(benchmark::State& state) {
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = std::make_unique<BenchData>();
|
|
|
|
for (int i = 0; i < 100; ++i) {
|
|
|
|
data->mutable_nums()->Add(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_add_100_ints_cpp);
|
|
|
|
|
|
|
|
void BM_add_100_ints_upb(benchmark::State& state) {
|
|
|
|
for (auto s : state) {
|
|
|
|
::protos::Arena arena;
|
|
|
|
auto data = ::protos::CreateMessage<benchmarks::protos::BenchData>(arena);
|
|
|
|
for (int i = 0; i < 100; ++i) {
|
|
|
|
data.add_nums(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_add_100_ints_upb);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(add_100_ints_rs);
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
void benchmark_thunk_add_num_rs(void* data, int32_t num);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BM_add_100_ints_rs_roundtrip(benchmark::State& state) {
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = std::make_unique<BenchData>();
|
|
|
|
for (int i = 0; i < 100; ++i) {
|
|
|
|
benchmark_thunk_add_num_rs((void*)data.get(), i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_add_100_ints_rs_roundtrip);
|
|
|
|
|
|
|
|
void BM_copy_from_100_ints_cpp(benchmark::State& state) {
|
|
|
|
auto source = std::make_unique<BenchData>();
|
|
|
|
for (int i = 0; i < 100; ++i) {
|
|
|
|
source->add_nums(i);
|
|
|
|
}
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = std::make_unique<BenchData>();
|
|
|
|
*data->mutable_nums() = source->nums();
|
|
|
|
ABSL_CHECK_EQ(data->nums()[99], 99);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_copy_from_100_ints_cpp);
|
|
|
|
|
|
|
|
void BM_copy_from_100_ints_upb(benchmark::State& state) {
|
|
|
|
::protos::Arena arena;
|
|
|
|
auto source = ::protos::CreateMessage<benchmarks::protos::BenchData>(arena);
|
|
|
|
for (int i = 0; i < 100; ++i) {
|
|
|
|
source.add_nums(i);
|
|
|
|
}
|
|
|
|
for (auto s : state) {
|
|
|
|
auto data = ::protos::CreateMessage<benchmarks::protos::BenchData>(arena);
|
|
|
|
data.resize_nums(source.nums_size());
|
|
|
|
std::copy(source.nums().begin(), source.nums().end(),
|
|
|
|
data.mutable_nums()->begin());
|
|
|
|
ABSL_CHECK_EQ(data.nums()[99], 99);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_copy_from_100_ints_upb);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(copy_from_100_ints_rs);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(extend_100_ints_rs);
|
|
|
|
|
|
|
|
EXTERN_BENCHMARK(extend_100_ints_vec_rs);
|
|
|
|
|
|
|
|
PROTO_BENCHMARK(sum_1000_ints_rs);
|
|
|
|
|
|
|
|
EXTERN_BENCHMARK(sum_1000_ints_vec_rs);
|
|
|
|
|
|
|
|
void BM_sum_1000_ints_cpp(benchmark::State& state) {
|
|
|
|
auto source = std::make_unique<BenchData>();
|
|
|
|
for (int i = 0; i < 1000; ++i) {
|
|
|
|
source->add_nums(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto s : state) {
|
|
|
|
int sum = 0;
|
|
|
|
for (auto x : source->nums()) {
|
|
|
|
sum += x;
|
|
|
|
}
|
|
|
|
ABSL_CHECK_EQ(sum, 499500);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_sum_1000_ints_cpp);
|
|
|
|
|
|
|
|
void BM_sum_1000_ints_upb(benchmark::State& state) {
|
|
|
|
::protos::Arena arena;
|
|
|
|
auto data = ::protos::CreateMessage<benchmarks::protos::BenchData>(arena);
|
|
|
|
for (int i = 0; i < 1000; ++i) {
|
|
|
|
data.add_nums(i);
|
|
|
|
}
|
|
|
|
for (auto s : state) {
|
|
|
|
int sum = 0;
|
|
|
|
for (auto x : data.nums()) {
|
|
|
|
sum += x;
|
|
|
|
}
|
|
|
|
ABSL_CHECK_EQ(sum, 499500);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_sum_1000_ints_upb);
|
|
|
|
|
|
|
|
void BM_sum_1000_ints_vector(benchmark::State& state) {
|
|
|
|
std::vector<int32_t> nums;
|
|
|
|
nums.reserve(1000);
|
|
|
|
for (int i = 0; i < 1000; ++i) {
|
|
|
|
nums.push_back(i);
|
|
|
|
}
|
|
|
|
for (auto s : state) {
|
|
|
|
int sum = 0;
|
|
|
|
for (auto x : nums) {
|
|
|
|
sum += x;
|
|
|
|
}
|
|
|
|
ABSL_CHECK_EQ(sum, 499500);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BENCHMARK(BM_sum_1000_ints_vector);
|