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;
length += last_buffer_bytes_written;
buffer->next = PacketBuffer::create();
buffer->next = PacketBuffer::create(size);
buffer = buffer->nextPacketBuffer();
if (reliable) {

View File

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

View File

@ -732,7 +732,7 @@ struct PacketWriter {
}
void serializeBytesAcrossBoundary(const void* data, int bytes);
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();
int size() { return length; }
@ -750,7 +750,21 @@ struct PacketWriter {
}
ProtocolVersion protocolVersion() const { return m_protocolVersion; }
void setProtocolVersion(ProtocolVersion pv) { m_protocolVersion = pv; }
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 );
};
@ -765,9 +779,8 @@ struct MakeSerializeSource : ISerializeSource {
using value_type = V;
virtual void serializePacketWriter(PacketWriter& w, bool useObjectSerializer) const {
if (useObjectSerializer) {
ObjectWriter writer;
writer.serialize(get());
w.serializeBytes(writer.toStringRef()); // TODO(atn34) Eliminate unnecessary memcpy
ObjectWriter writer([&](size_t size) { return w.writeBytes(size); });
writer.serialize(get()); // Writes directly into buffer supplied by |w|
} else {
static_cast<T const*>(this)->serialize(w);
}