blob: 4d3a8706d036c7c49075f99b15437c0bb92d590b [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2025 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include <cstddef>
#include <string>
#include <type_traits>
#include <vector>
#include <benchmark/benchmark.h>
#include <gtest/gtest.h>
#include "absl/container/flat_hash_set.h"
#include "upb/mem/alloc.h"
#include "upb/mem/arena.h"
#include "upb/message/message.h"
#include "upb/mini_table/message.h"
#include "upb/wire/decode.h"
#include "upb/wire/decode_fast/combinations.h"
#include "upb/wire/test_util/field_types.h"
#include "upb/wire/test_util/make_mini_table.h"
#include "upb/wire/test_util/wire_message.h"
// Must be last.
#include "upb/port/def.inc"
namespace upb {
namespace test {
namespace {
void BM_Decode(benchmark::State& state, const upb_MiniTable* mt,
std::string payload, bool alias, bool initial_block) {
char mem[4096];
int decode_options = 0;
for (auto s : state) {
upb_Arena* arena = initial_block
? upb_Arena_Init(mem, 4096, &upb_alloc_global)
: upb_Arena_New();
upb_Message* msg = upb_Message_New(mt, arena);
upb_DecodeStatus result = upb_Decode(payload.data(), payload.size(), msg,
mt, nullptr, decode_options, arena);
ASSERT_EQ(result, kUpb_DecodeStatus_Ok) << upb_DecodeStatus_String(result);
upb_Arena_Free(arena);
}
state.SetBytesProcessed(state.iterations() * payload.size());
}
[[maybe_unused]] upb_Arena* benchmark_registration = [] {
upb_Arena* arena = upb_Arena_New();
std::vector<size_t> sizes{8, 64, 512};
for (size_t size : sizes) {
absl::flat_hash_set<upb_DecodeFast_Type> fast_types;
ForEachType([&](auto&& type) {
using Type = std::remove_reference_t<decltype(type)>;
// We only need to benchmark each wire type once, since they are all
// treated the same by the decoder.
if (!fast_types.insert(Type::kFastType).second) return;
std::vector<bool> initial_block{true, false};
for (bool init : initial_block) {
auto [mt, field] = MiniTable::MakeSingleFieldTable<Type>(
1, kUpb_DecodeFast_Scalar, arena);
std::string payload;
while (payload.size() < size) {
payload.append(ToBinaryPayload(wire_types::WireMessage{
{1, Type::WireValue(typename Type::Value{})}}));
}
::benchmark::RegisterBenchmark(
absl::StrFormat("BM_Decode/%s/%zu/%s", Type::kName, size,
init ? "InitialBlock" : "NoInitialBlock")
.c_str(),
BM_Decode, mt, payload, false, init);
}
});
}
return arena;
}();
} // namespace
} // namespace test
} // namespace upb