diff options
Diffstat (limited to 'devtools/shared/heapsnapshot/CoreDump.proto')
-rw-r--r-- | devtools/shared/heapsnapshot/CoreDump.proto | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/devtools/shared/heapsnapshot/CoreDump.proto b/devtools/shared/heapsnapshot/CoreDump.proto new file mode 100644 index 000000000..24a223e11 --- /dev/null +++ b/devtools/shared/heapsnapshot/CoreDump.proto @@ -0,0 +1,143 @@ +/* -*- Mode: protobuf; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// # Core Dumps +// +// A core dump is a serialized snapshot of the heap graph. We serialize the heap +// as a series of protobuf messages with each message prefixed by its Varint32 +// byte size so we can delimit individual protobuf messages (protobuf parsers +// cannot determine where a message ends on their own). +// +// The first protobuf message is an instance of the `Metadata` message. All +// subsequent messages will be instances of the `Node` message. The first of +// these `Node` messages is the root node of the serialized heap graph. Here is +// a diagram of our core dump format: +// +// +-----------------------------------------------------------------------+ +// | Varint32: The size of following `Metadata` message. | +// +-----------------------------------------------------------------------+ +// | message: The core dump `Metadata` message. | +// +-----------------------------------------------------------------------+ +// | Varint32: The size of the following `Node` message. | +// +-----------------------------------------------------------------------+ +// | message: The first `Node` message. This is the root node. | +// +-----------------------------------------------------------------------+ +// | Varint32: The size of the following `Node` message. | +// +-----------------------------------------------------------------------+ +// | message: A `Node` message. | +// +-----------------------------------------------------------------------+ +// | Varint32: The size of the following `Node` message. | +// +-----------------------------------------------------------------------+ +// | message: A `Node` message. | +// +-----------------------------------------------------------------------+ +// | . | +// | . | +// | . | +// +-----------------------------------------------------------------------+ +// +// Core dumps should always be written with a +// `google::protobuf::io::GzipOutputStream` and read from a +// `google::protobuf::io::GzipInputStream`. +// +// Note that all strings are de-duplicated. The first time the N^th unique +// string is encountered, the full string is serialized. Subsequent times that +// same string is encountered, it is referenced by N. This de-duplication +// happens across string properties, not on a per-property basis. For example, +// if the same K^th unique string is first used as an Edge::EdgeNameOrRef and +// then as a StackFrame::Data::FunctionDisplayNameOrRef, the first will be the +// actual string as the functionDisplayName oneof property, and the second will +// be a reference to the first as the edgeNameRef oneof property whose value is +// K. +// +// We would ordinarily abstract these de-duplicated strings with messages of +// their own, but unfortunately, the protobuf compiler does not have a way to +// inline a messsage within another message and the child message must be +// referenced by pointer. This leads to extra mallocs that we wish to avoid. + + +package mozilla.devtools.protobuf; + +// A collection of metadata about this core dump. +message Metadata { + // Number of microseconds since midnight (00:00:00) 1 January 1970 UTC. + optional uint64 timeStamp = 1; +} + +// A serialized version of `JS::ubi::StackFrame`. Older parent frame tails are +// de-duplicated to cut down on [de]serialization and size costs. +message StackFrame { + oneof StackFrameType { + // This is the first time this stack frame has been serialized, and so + // here is all of its data. + Data data = 1; + // A reference to a stack frame that has already been serialized and has + // the given number as its id. + uint64 ref = 2; + } + + message Data { + optional uint64 id = 1; + optional StackFrame parent = 2; + optional uint32 line = 3; + optional uint32 column = 4; + + // De-duplicated two-byte string. + oneof SourceOrRef { + bytes source = 5; + uint64 sourceRef = 6; + } + + // De-duplicated two-byte string. + oneof FunctionDisplayNameOrRef { + bytes functionDisplayName = 7; + uint64 functionDisplayNameRef = 8; + } + + optional bool isSystem = 9; + optional bool isSelfHosted = 10; + } +} + +// A serialized version of `JS::ubi::Node` and its outgoing edges. +message Node { + optional uint64 id = 1; + + // De-duplicated two-byte string. + oneof TypeNameOrRef { + bytes typeName = 2; + uint64 typeNameRef = 3; + } + + optional uint64 size = 4; + repeated Edge edges = 5; + optional StackFrame allocationStack = 6; + + // De-duplicated one-byte string. + oneof JSObjectClassNameOrRef { + bytes jsObjectClassName = 7; + uint64 jsObjectClassNameRef = 8; + } + + // JS::ubi::CoarseType. Defaults to Other. + optional uint32 coarseType = 9 [default = 0]; + + // De-duplicated one-byte string. + oneof ScriptFilenameOrRef { + bytes scriptFilename = 10; + uint64 scriptFilenameRef = 11; + } +} + +// A serialized edge from the heap graph. +message Edge { + optional uint64 referent = 1; + + // De-duplicated two-byte string. + oneof EdgeNameOrRef { + bytes name = 2; + uint64 nameRef = 3; + } +} |