mirror of
https://github.com/google/flatbuffers.git
synced 2026-07-02 16:58:19 +00:00
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
This commit is contained in:
@@ -37,6 +37,7 @@ set(FlatBenchmark_SRCS
|
|||||||
${CPP_BENCH_DIR}/benchmark_main.cpp
|
${CPP_BENCH_DIR}/benchmark_main.cpp
|
||||||
${CPP_FB_BENCH_DIR}/fb_bench.cpp
|
${CPP_FB_BENCH_DIR}/fb_bench.cpp
|
||||||
${CPP_RAW_BENCH_DIR}/raw_bench.cpp
|
${CPP_RAW_BENCH_DIR}/raw_bench.cpp
|
||||||
|
${CPP_BENCH_FB_GEN}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Generate the flatbuffers benchmark code from the flatbuffers schema using
|
# Generate the flatbuffers benchmark code from the flatbuffers schema using
|
||||||
|
|||||||
@@ -93,4 +93,4 @@ static void BM_Raw_Use(benchmark::State &state) {
|
|||||||
std::unique_ptr<Bench> bench = NewRawBench();
|
std::unique_ptr<Bench> bench = NewRawBench();
|
||||||
Use(state, bench, buffer, 218812692406581874);
|
Use(state, bench, buffer, 218812692406581874);
|
||||||
}
|
}
|
||||||
BENCHMARK(BM_Raw_Use);
|
BENCHMARK(BM_Raw_Use);
|
||||||
|
|||||||
@@ -285,20 +285,20 @@ class FlatBufferBuilder {
|
|||||||
FieldLoc fl = { off, field };
|
FieldLoc fl = { off, field };
|
||||||
buf_.scratch_push_small(fl);
|
buf_.scratch_push_small(fl);
|
||||||
num_field_loc++;
|
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.
|
// Like PushElement, but additionally tracks the field this represents.
|
||||||
template<typename T> void AddElement(voffset_t field, T e, T def) {
|
template<typename T> void AddElement(voffset_t field, T e, T def) {
|
||||||
// We don't serialize values equal to the default.
|
// We don't serialize values equal to the default.
|
||||||
if (IsTheSameAs(e, def) && !force_defaults_) return;
|
if (IsTheSameAs(e, def) && !force_defaults_) return;
|
||||||
auto off = PushElement(e);
|
TrackField(field, PushElement(e));
|
||||||
TrackField(field, off);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void AddElement(voffset_t field, T e) {
|
template<typename T> void AddElement(voffset_t field, T e) {
|
||||||
auto off = PushElement(e);
|
TrackField(field, PushElement(e));
|
||||||
TrackField(field, off);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
|
template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
|
||||||
@@ -324,8 +324,9 @@ class FlatBufferBuilder {
|
|||||||
// Align to ensure GetSize() below is correct.
|
// Align to ensure GetSize() below is correct.
|
||||||
Align(sizeof(uoffset_t));
|
Align(sizeof(uoffset_t));
|
||||||
// Offset must refer to something already in buffer.
|
// Offset must refer to something already in buffer.
|
||||||
FLATBUFFERS_ASSERT(off && off <= GetSize());
|
const uoffset_t size = GetSize();
|
||||||
return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
|
FLATBUFFERS_ASSERT(off && off <= size);
|
||||||
|
return size - off + static_cast<uoffset_t>(sizeof(uoffset_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotNested() {
|
void NotNested() {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class vector_downward {
|
|||||||
initial_size_(initial_size),
|
initial_size_(initial_size),
|
||||||
buffer_minalign_(buffer_minalign),
|
buffer_minalign_(buffer_minalign),
|
||||||
reserved_(0),
|
reserved_(0),
|
||||||
|
size_(0),
|
||||||
buf_(nullptr),
|
buf_(nullptr),
|
||||||
cur_(nullptr),
|
cur_(nullptr),
|
||||||
scratch_(nullptr) {}
|
scratch_(nullptr) {}
|
||||||
@@ -49,6 +50,7 @@ class vector_downward {
|
|||||||
initial_size_(other.initial_size_),
|
initial_size_(other.initial_size_),
|
||||||
buffer_minalign_(other.buffer_minalign_),
|
buffer_minalign_(other.buffer_minalign_),
|
||||||
reserved_(other.reserved_),
|
reserved_(other.reserved_),
|
||||||
|
size_(other.size_),
|
||||||
buf_(other.buf_),
|
buf_(other.buf_),
|
||||||
cur_(other.cur_),
|
cur_(other.cur_),
|
||||||
scratch_(other.scratch_) {
|
scratch_(other.scratch_) {
|
||||||
@@ -86,6 +88,7 @@ class vector_downward {
|
|||||||
reserved_ = 0;
|
reserved_ = 0;
|
||||||
cur_ = nullptr;
|
cur_ = nullptr;
|
||||||
}
|
}
|
||||||
|
size_ = 0;
|
||||||
clear_scratch();
|
clear_scratch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,17 +142,18 @@ class vector_downward {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t *make_space(size_t len) {
|
inline uint8_t *make_space(size_t len) {
|
||||||
size_t space = ensure_space(len);
|
if (len) {
|
||||||
cur_ -= space;
|
ensure_space(len);
|
||||||
|
cur_ -= len;
|
||||||
|
size_ += static_cast<uoffset_t>(len);
|
||||||
|
}
|
||||||
return cur_;
|
return cur_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns nullptr if using the DefaultAllocator.
|
// Returns nullptr if using the DefaultAllocator.
|
||||||
Allocator *get_custom_allocator() { return allocator_; }
|
Allocator *get_custom_allocator() { return allocator_; }
|
||||||
|
|
||||||
uoffset_t size() const {
|
inline uoffset_t size() const { return size_; }
|
||||||
return static_cast<uoffset_t>(reserved_ - static_cast<size_t>(cur_ - buf_));
|
|
||||||
}
|
|
||||||
|
|
||||||
uoffset_t scratch_size() const {
|
uoffset_t scratch_size() const {
|
||||||
return static_cast<uoffset_t>(scratch_ - buf_);
|
return static_cast<uoffset_t>(scratch_ - buf_);
|
||||||
@@ -203,7 +207,11 @@ class vector_downward {
|
|||||||
memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
|
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<uoffset_t>(bytes_to_remove);
|
||||||
|
}
|
||||||
|
|
||||||
void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
|
void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
|
||||||
|
|
||||||
void swap(vector_downward &other) {
|
void swap(vector_downward &other) {
|
||||||
@@ -213,6 +221,7 @@ class vector_downward {
|
|||||||
swap(initial_size_, other.initial_size_);
|
swap(initial_size_, other.initial_size_);
|
||||||
swap(buffer_minalign_, other.buffer_minalign_);
|
swap(buffer_minalign_, other.buffer_minalign_);
|
||||||
swap(reserved_, other.reserved_);
|
swap(reserved_, other.reserved_);
|
||||||
|
swap(size_, other.size_);
|
||||||
swap(buf_, other.buf_);
|
swap(buf_, other.buf_);
|
||||||
swap(cur_, other.cur_);
|
swap(cur_, other.cur_);
|
||||||
swap(scratch_, other.scratch_);
|
swap(scratch_, other.scratch_);
|
||||||
@@ -234,6 +243,7 @@ class vector_downward {
|
|||||||
size_t initial_size_;
|
size_t initial_size_;
|
||||||
size_t buffer_minalign_;
|
size_t buffer_minalign_;
|
||||||
size_t reserved_;
|
size_t reserved_;
|
||||||
|
uoffset_t size_;
|
||||||
uint8_t *buf_;
|
uint8_t *buf_;
|
||||||
uint8_t *cur_; // Points at location between empty (below) and used (above).
|
uint8_t *cur_; // Points at location between empty (below) and used (above).
|
||||||
uint8_t *scratch_; // Points to the end of the scratchpad in use.
|
uint8_t *scratch_; // Points to the end of the scratchpad in use.
|
||||||
|
|||||||
Reference in New Issue
Block a user