From 9e4ca857b6dadf116703f612187e33b7d4bb6688 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Mon, 22 Nov 2021 19:50:42 -0800 Subject: [PATCH] Vector Downward GetSize optimization (#6925) * Added Google benchmarks (and gtests) * Separate benchmark CMakeLists.txt to its own file * Move output directory to target just flatbenchmark * Reduced from encoding 210ns -> 188ns * store size_ as uoffset_t * fixed windows c4267 warning --- benchmarks/CMakeLists.txt | 1 + benchmarks/cpp/benchmark_main.cpp | 2 +- include/flatbuffers/flatbuffer_builder.h | 15 ++++++++------- include/flatbuffers/vector_downward.h | 22 ++++++++++++++++------ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 3d3032c6e..8d49c35d1 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -37,6 +37,7 @@ set(FlatBenchmark_SRCS ${CPP_BENCH_DIR}/benchmark_main.cpp ${CPP_FB_BENCH_DIR}/fb_bench.cpp ${CPP_RAW_BENCH_DIR}/raw_bench.cpp + ${CPP_BENCH_FB_GEN} ) # Generate the flatbuffers benchmark code from the flatbuffers schema using diff --git a/benchmarks/cpp/benchmark_main.cpp b/benchmarks/cpp/benchmark_main.cpp index 720f94e65..63807a5dd 100644 --- a/benchmarks/cpp/benchmark_main.cpp +++ b/benchmarks/cpp/benchmark_main.cpp @@ -93,4 +93,4 @@ static void BM_Raw_Use(benchmark::State &state) { std::unique_ptr bench = NewRawBench(); Use(state, bench, buffer, 218812692406581874); } -BENCHMARK(BM_Raw_Use); \ No newline at end of file +BENCHMARK(BM_Raw_Use); diff --git a/include/flatbuffers/flatbuffer_builder.h b/include/flatbuffers/flatbuffer_builder.h index 7db48e30c..ce40f7b09 100644 --- a/include/flatbuffers/flatbuffer_builder.h +++ b/include/flatbuffers/flatbuffer_builder.h @@ -285,20 +285,20 @@ class FlatBufferBuilder { FieldLoc fl = { off, field }; buf_.scratch_push_small(fl); num_field_loc++; - max_voffset_ = (std::max)(max_voffset_, field); + if (field > max_voffset_) { + max_voffset_ = field; + } } // Like PushElement, but additionally tracks the field this represents. template void AddElement(voffset_t field, T e, T def) { // We don't serialize values equal to the default. if (IsTheSameAs(e, def) && !force_defaults_) return; - auto off = PushElement(e); - TrackField(field, off); + TrackField(field, PushElement(e)); } template void AddElement(voffset_t field, T e) { - auto off = PushElement(e); - TrackField(field, off); + TrackField(field, PushElement(e)); } template void AddOffset(voffset_t field, Offset off) { @@ -324,8 +324,9 @@ class FlatBufferBuilder { // Align to ensure GetSize() below is correct. Align(sizeof(uoffset_t)); // Offset must refer to something already in buffer. - FLATBUFFERS_ASSERT(off && off <= GetSize()); - return GetSize() - off + static_cast(sizeof(uoffset_t)); + const uoffset_t size = GetSize(); + FLATBUFFERS_ASSERT(off && off <= size); + return size - off + static_cast(sizeof(uoffset_t)); } void NotNested() { diff --git a/include/flatbuffers/vector_downward.h b/include/flatbuffers/vector_downward.h index 8088b10c5..339139185 100644 --- a/include/flatbuffers/vector_downward.h +++ b/include/flatbuffers/vector_downward.h @@ -38,6 +38,7 @@ class vector_downward { initial_size_(initial_size), buffer_minalign_(buffer_minalign), reserved_(0), + size_(0), buf_(nullptr), cur_(nullptr), scratch_(nullptr) {} @@ -49,6 +50,7 @@ class vector_downward { initial_size_(other.initial_size_), buffer_minalign_(other.buffer_minalign_), reserved_(other.reserved_), + size_(other.size_), buf_(other.buf_), cur_(other.cur_), scratch_(other.scratch_) { @@ -86,6 +88,7 @@ class vector_downward { reserved_ = 0; cur_ = nullptr; } + size_ = 0; clear_scratch(); } @@ -139,17 +142,18 @@ class vector_downward { } inline uint8_t *make_space(size_t len) { - size_t space = ensure_space(len); - cur_ -= space; + if (len) { + ensure_space(len); + cur_ -= len; + size_ += static_cast(len); + } return cur_; } // Returns nullptr if using the DefaultAllocator. Allocator *get_custom_allocator() { return allocator_; } - uoffset_t size() const { - return static_cast(reserved_ - static_cast(cur_ - buf_)); - } + inline uoffset_t size() const { return size_; } uoffset_t scratch_size() const { return static_cast(scratch_ - buf_); @@ -203,7 +207,11 @@ class vector_downward { memset(make_space(zero_pad_bytes), 0, zero_pad_bytes); } - void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; } + void pop(size_t bytes_to_remove) { + cur_ += bytes_to_remove; + size_ -= static_cast(bytes_to_remove); + } + void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; } void swap(vector_downward &other) { @@ -213,6 +221,7 @@ class vector_downward { swap(initial_size_, other.initial_size_); swap(buffer_minalign_, other.buffer_minalign_); swap(reserved_, other.reserved_); + swap(size_, other.size_); swap(buf_, other.buf_); swap(cur_, other.cur_); swap(scratch_, other.scratch_); @@ -234,6 +243,7 @@ class vector_downward { size_t initial_size_; size_t buffer_minalign_; size_t reserved_; + uoffset_t size_; uint8_t *buf_; uint8_t *cur_; // Points at location between empty (below) and used (above). uint8_t *scratch_; // Points to the end of the scratchpad in use.