Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1346)

Unified Diff: base/trace_event/v2/append_only_proto_message.cc

Issue 1947373002: Tracing V2 prototype [NOT FOR REVIEW] Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: WORKS Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/trace_event/v2/append_only_proto_message.cc
diff --git a/base/trace_event/v2/append_only_proto_message.cc b/base/trace_event/v2/append_only_proto_message.cc
new file mode 100644
index 0000000000000000000000000000000000000000..85a0947717c8b9d819e804b112f6820efd1a48ae
--- /dev/null
+++ b/base/trace_event/v2/append_only_proto_message.cc
@@ -0,0 +1,174 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/trace_event/v2/append_only_proto_message.h"
+
+#include "base/logging.h"
+#include "base/trace_event/v2/proto_utils.h"
+#include "build/build_config.h"
+
+
+// TODO size vs length naming inconsistency.
+// TODO bitmap for mandatory / optional fields
+
+namespace {
+
+enum {
+ PROTO_VARINT = 0,
+ PROTO_FIXED_64BIT = 1,
+ PROTO_LENGTH_LIMITED = 2,
+ PROTO_FIXED_32BIT = 5,
+};
+
+} // namespace
+
+namespace base {
+namespace trace_event {
+namespace v2 {
+
+// static
+const size_t AppendOnlyProtoMessage::kMaxMessageLength =
+ 1ul << (AppendOnlyProtoMessage::kMaxMessageLengthFieldSize * 7);
+
+AppendOnlyProtoMessage::AppendOnlyProtoMessage()
+ : buffer_(nullptr),
+ size_(0),
+ write_size_field_on_finalization_(false),
+ size_already_written_(0),
+ current_nested_message_(nullptr),
+ sealed_(false) {}
+
+AppendOnlyProtoMessage::~AppendOnlyProtoMessage() {}
+
+size_t AppendOnlyProtoMessage::Finalize() {
+ if (sealed_)
+ return size_;
+
+ if (current_nested_message_)
+ EndNestedMessage();
+
+ if (write_size_field_on_finalization_) {
+ // Write the length of the nested message a posteriori, forcing a 32-bit
+ // leading-zero varint. This is a slight bending of the proto encoding,
+ // essentially size = 7 gets encoded as 0x87,0x80,0x80,0x00 instead of 0x07.
+ // The problem here is that we cannot know upfront how big the nested message
+ // was. There is precedent for this (TODO link internal bug).
+ // TODO optimization: upon beginmessage we could get a promise of the max
+ // length of the submessage to avoid wasting 2 bytes if we know upfront that
+ // the message is going to be always < 64k.
+ DCHECK_LT(size_, kMaxMessageLength);
+ uint8_t word[kMaxMessageLengthFieldSize];
+ ProtoUtils::EncodeRedundantVarIntUnsigned(size_ - size_already_written_,
+ kMaxMessageLengthFieldSize,
+ word);
+ buffer_->WriteReservedBytes(size_field_, word, kMaxMessageLengthFieldSize);
+ }
+
+ // No more changes allowed.
+ sealed_ = true;
+ return size_;
+}
+
+void AppendOnlyProtoMessage::WriteToBuffer(const uint8_t* src, size_t size) {
+ buffer_->WriteBytes(src, size);
+ size_ += size;
+}
+
+void AppendOnlyProtoMessage::AppendVarIntSigned(uint32_t field_id,
+ int64_t value) {
+ // TODO ZigZag encoding.
+ AppendVarIntUnsigned(field_id, value); // HACK, this is not supporting signed.
+}
+
+void AppendOnlyProtoMessage::AppendVarIntUnsigned(uint32_t field_id,
+ uint64_t value) {
+ if (current_nested_message_)
+ EndNestedMessage();
+
+ uint8_t data[32];
+ size_t data_size;
+ data_size = ProtoUtils::EncodeVarIntUnsigned(ProtoUtils::GetVarIntFieldHeader(field_id), data);
+ data_size += ProtoUtils::EncodeVarIntUnsigned(value, &data[data_size]);
+ WriteToBuffer(data, data_size);
+}
+
+void AppendOnlyProtoMessage::AppendFloat(uint32_t field_id, float value) {
+ if (current_nested_message_)
+ EndNestedMessage();
+
+ uint8_t data[32];
+ size_t data_size;
+ data_size = ProtoUtils::EncodeVarIntUnsigned(ProtoUtils::GetFixed32FieldHeader(field_id), data);
+
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+ memcpy(&data[data_size], &value, sizeof(value));
+#else
+#error big-endian encoding not implemented.
+#endif
+
+ data_size += sizeof(value);
+ WriteToBuffer(data, data_size);
+}
+
+void AppendOnlyProtoMessage::AppendDouble(uint32_t field_id, double value) {
+ if (current_nested_message_)
+ EndNestedMessage();
+
+ uint8_t data[32];
+ size_t data_size;
+ data_size = ProtoUtils::EncodeVarIntUnsigned(ProtoUtils::GetFixed64FieldHeader(field_id), data);
+ memcpy(&data[data_size], &value, sizeof(value));
+ data_size += sizeof(value);
+ WriteToBuffer(data, data_size);
+}
+
+void AppendOnlyProtoMessage::AppendString(uint32_t field_id, const char* str) {
+ if (current_nested_message_)
+ EndNestedMessage();
+
+ const size_t str_length = strlen(str);
+ AppendBytes(field_id, str, str_length);
+}
+
+void AppendOnlyProtoMessage::AppendBytes(uint32_t field_id, const void* value, size_t size) {
+ if (current_nested_message_)
+ EndNestedMessage();
+
+ // Write the proto preamble (field id, type and length of the buffer).
+ uint8_t data[32];
+ size_t data_size;
+ data_size = ProtoUtils::EncodeVarIntUnsigned(ProtoUtils::GetLengthLimitedFieldHeader(field_id), data);
+ data_size += ProtoUtils::EncodeVarIntUnsigned(size, &data[data_size]);
+ WriteToBuffer(data, data_size);
+
+ // Write the actual buffer.
+ WriteToBuffer(reinterpret_cast<const uint8_t*>(value), size);
+}
+
+void AppendOnlyProtoMessage::BeginNestedMessage(
+ uint32_t field_id,
+ AppendOnlyProtoMessage* message) {
+ if (current_nested_message_)
+ EndNestedMessage();
+
+ message->set_buffer_writer(buffer_writer());
+ uint8_t data[32];
+ size_t data_size;
+ data_size = ProtoUtils::EncodeVarIntUnsigned(ProtoUtils::GetLengthLimitedFieldHeader(field_id), data);
+ WriteToBuffer(data, data_size);
+
+ // The length of the nested message cannot be known upfront. So right now
+ // just reserve the bytes to encode the size after the nested message is done.
+ message->set_write_size_field_on_finalization(buffer_->ReserveBytes(kMaxMessageLengthFieldSize));
+ current_nested_message_ = message;
+}
+
+void AppendOnlyProtoMessage::EndNestedMessage() {
+ size_ += current_nested_message_->Finalize();
+ current_nested_message_ = nullptr;
+}
+
+} // namespace v2
+} // namespace trace_event
+} // namespace base
« no previous file with comments | « base/trace_event/v2/append_only_proto_message.h ('k') | base/trace_event/v2/append_only_proto_message_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698