From 87e29b25def0159ac3d6607595643c2131d7b811 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Fri, 27 Jan 2017 11:26:35 -0800 Subject: [PATCH] Some small speed optimizations to the core copying functions. Change-Id: Id8c1afb84f4ab0e2edca4290e3de5589fa06e578 Tested: on Linux. --- include/flatbuffers/flatbuffers.h | 26 +++++++++++++++++++------- samples/monster_generated.h | 4 ++-- tests/monster_test_generated.h | 4 ++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 1d979cc..d1520f5 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -560,18 +560,30 @@ class vector_downward { uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; } - // push() & fill() are most frequently called with small byte counts (<= 4), - // which is why we're using loops rather than calling memcpy/memset. void push(const uint8_t *bytes, size_t num) { auto dest = make_space(num); - for (size_t i = 0; i < num; i++) dest[i] = bytes[i]; + memcpy(dest, bytes, num); } + // Specialized version of push() that avoids memcpy call for small data. + template void push_small(T little_endian_t) { + auto dest = make_space(sizeof(T)); + *reinterpret_cast(dest) = little_endian_t; + } + + // fill() is most frequently called with small byte counts (<= 4), + // which is why we're using loops rather than calling memset. void fill(size_t zero_pad_bytes) { auto dest = make_space(zero_pad_bytes); for (size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0; } + // Version for when we know the size is larger. + void fill_big(size_t zero_pad_bytes) { + auto dest = make_space(zero_pad_bytes); + memset(dest, 0, zero_pad_bytes); + } + void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; } private: @@ -762,7 +774,7 @@ FLATBUFFERS_FINAL_CLASS AssertScalarT(); T litle_endian_element = EndianScalar(element); Align(sizeof(T)); - PushBytes(reinterpret_cast(&litle_endian_element), sizeof(T)); + buf_.push_small(litle_endian_element); return GetSize(); } @@ -794,7 +806,7 @@ FLATBUFFERS_FINAL_CLASS template void AddStruct(voffset_t field, const T *structptr) { if (!structptr) return; // Default, don't store. Align(AlignOf()); - PushBytes(reinterpret_cast(structptr), sizeof(T)); + buf_.push_small(*structptr); TrackField(field, GetSize()); } @@ -845,7 +857,7 @@ FLATBUFFERS_FINAL_CLASS // Write a vtable, which consists entirely of voffset_t elements. // It starts with the number of offsets, followed by a type id, followed // by the offsets themselves. In reverse: - buf_.fill(numfields * sizeof(voffset_t)); + buf_.fill_big(numfields * sizeof(voffset_t)); auto table_object_size = vtableoffsetloc - start; assert(table_object_size < 0x10000); // Vtable use 16bit offsets. PushElement(static_cast(table_object_size)); @@ -1239,7 +1251,7 @@ FLATBUFFERS_FINAL_CLASS minalign_); if (file_identifier) { assert(strlen(file_identifier) == kFileIdentifierLength); - buf_.push(reinterpret_cast(file_identifier), + PushBytes(reinterpret_cast(file_identifier), kFileIdentifierLength); } PushElement(ReferTo(root)); // Location of root. diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 0cf21f7..61167e4 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -515,8 +515,8 @@ inline bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuf if (values->size() != types->size()) return false; for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { if (!VerifyEquipment( - verifier, values->Get(i), types->GetEnum(i))) { - return false; + verifier, values->Get(i), types->GetEnum(i))) { + return false; } } return true; diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index b96f85e..6978049 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -1203,8 +1203,8 @@ inline bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers:: if (values->size() != types->size()) return false; for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { if (!VerifyAny( - verifier, values->Get(i), types->GetEnum(i))) { - return false; + verifier, values->Get(i), types->GetEnum(i))) { + return false; } } return true; -- 2.7.4