Eliminate unnecessary memcpy

This commit is contained in:
Andrew Noyes 2019-07-01 18:14:32 -07:00 committed by mpilman
parent 70f0726185
commit 137936762d
3 changed files with 36 additions and 15 deletions

View File

@ -53,11 +53,11 @@ void PacketWriter::serializeBytesAcrossBoundary(const void* data, int bytes) {
} }
} }
void PacketWriter::nextBuffer() { void PacketWriter::nextBuffer(size_t size) {
auto last_buffer_bytes_written = buffer->bytes_written; auto last_buffer_bytes_written = buffer->bytes_written;
length += last_buffer_bytes_written; length += last_buffer_bytes_written;
buffer->next = PacketBuffer::create(); buffer->next = PacketBuffer::create(size);
buffer = buffer->nextPacketBuffer(); buffer = buffer->nextPacketBuffer();
if (reliable) { if (reliable) {

View File

@ -99,18 +99,24 @@ private:
class ObjectWriter { class ObjectWriter {
public: public:
ObjectWriter() = default;
explicit ObjectWriter(std::function<uint8_t*(size_t)> customAllocator) : customAllocator(customAllocator) {}
template <class... Items> template <class... Items>
void serialize(FileIdentifier file_identifier, Items const&... items) { void serialize(FileIdentifier file_identifier, Items const&... items) {
ASSERT(data == nullptr); // object serializer can only serialize one object ASSERT(data == nullptr); // object serializer can only serialize one object
int allocations = 0; if (customAllocator) {
auto allocator = [this, &allocations](size_t size_) { save_members(customAllocator, file_identifier, items...);
++allocations; } else {
size = size_; int allocations = 0;
data = new (arena) uint8_t[size]; auto allocator = [this, &allocations](size_t size_) {
return data; ++allocations;
}; size = size_;
save_members(allocator, file_identifier, items...); data = new (arena) uint8_t[size];
ASSERT(allocations == 1); return data;
};
save_members(allocator, file_identifier, items...);
ASSERT(allocations == 1);
}
} }
template <class Item> template <class Item>
@ -123,6 +129,7 @@ public:
} }
Standalone<StringRef> toString() const { Standalone<StringRef> toString() const {
ASSERT(!customAllocator);
return Standalone<StringRef>(toStringRef(), arena); return Standalone<StringRef>(toStringRef(), arena);
} }
@ -135,6 +142,7 @@ public:
private: private:
Arena arena; Arena arena;
std::function<uint8_t*(size_t)> customAllocator;
uint8_t* data = nullptr; uint8_t* data = nullptr;
int size = 0; int size = 0;
}; };

View File

@ -732,7 +732,7 @@ struct PacketWriter {
} }
void serializeBytesAcrossBoundary(const void* data, int bytes); void serializeBytesAcrossBoundary(const void* data, int bytes);
void writeAhead( int bytes, struct SplitBuffer* ); void writeAhead( int bytes, struct SplitBuffer* );
void nextBuffer(); void nextBuffer(size_t size = 0 /* downstream it will default to at least 4k minus some padding */);
PacketBuffer* finish(); PacketBuffer* finish();
int size() { return length; } int size() { return length; }
@ -750,7 +750,21 @@ struct PacketWriter {
} }
ProtocolVersion protocolVersion() const { return m_protocolVersion; } ProtocolVersion protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(ProtocolVersion pv) { m_protocolVersion = pv; } void setProtocolVersion(ProtocolVersion pv) { m_protocolVersion = pv; }
private: private:
uint8_t* writeBytes(size_t size) {
if (size > buffer->bytes_unwritten()) {
nextBuffer(size);
ASSERT(buffer->size() >= size);
}
uint8_t* result = buffer->data() + buffer->bytes_written;
buffer->bytes_written += size;
return result;
}
template <class, class>
friend class MakeSerializeSource;
void init( PacketBuffer* buf, ReliablePacket* reliable ); void init( PacketBuffer* buf, ReliablePacket* reliable );
}; };
@ -765,9 +779,8 @@ struct MakeSerializeSource : ISerializeSource {
using value_type = V; using value_type = V;
virtual void serializePacketWriter(PacketWriter& w, bool useObjectSerializer) const { virtual void serializePacketWriter(PacketWriter& w, bool useObjectSerializer) const {
if (useObjectSerializer) { if (useObjectSerializer) {
ObjectWriter writer; ObjectWriter writer([&](size_t size) { return w.writeBytes(size); });
writer.serialize(get()); writer.serialize(get()); // Writes directly into buffer supplied by |w|
w.serializeBytes(writer.toStringRef()); // TODO(atn34) Eliminate unnecessary memcpy
} else { } else {
static_cast<T const*>(this)->serialize(w); static_cast<T const*>(this)->serialize(w);
} }