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

Side by Side Diff: chrome/profiling/memlog_stream_parser.cc

Issue 2943733002: Add out-of-process memory logging stream parsing. (Closed)
Patch Set: Add TODO Created 3 years, 6 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 unified diff | Download patch
« no previous file with comments | « chrome/profiling/memlog_stream_parser.h ('k') | chrome/profiling/profiling_globals.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/profiling/memlog_stream_parser.h"
6
7 #include <algorithm>
8
9 #include "base/containers/stack_container.h"
10 #include "base/strings/stringprintf.h"
11 #include "chrome/common/profiling/memlog_stream.h"
12 #include "chrome/profiling/address.h"
13 #include "chrome/profiling/backtrace.h"
14 #include "chrome/profiling/profiling_globals.h"
15
16 namespace profiling {
17
18 namespace {
19
20 using AddressVector = base::StackVector<Address, 128>;
21
22 } // namespace
23
24 MemlogStreamParser::Block::Block(std::unique_ptr<char[]> d, size_t s)
25 : data(std::move(d)), size(s) {}
26
27 MemlogStreamParser::MemlogStreamParser(MemlogReceiver* receiver)
28 : receiver_(receiver) {}
29
30 MemlogStreamParser::~MemlogStreamParser() {}
31
32 void MemlogStreamParser::OnStreamData(std::unique_ptr<char[]> data, size_t sz) {
33 blocks_.emplace_back(std::move(data), sz);
34
35 if (!received_header_) {
36 received_header_ = true;
37 ReadStatus status = ParseHeader();
38 if (status != READ_OK)
39 return; // TODO(brettw) signal error.
40 }
41
42 while (true) {
43 uint32_t msg_type;
44 if (!PeekBytes(sizeof(msg_type), &msg_type))
45 return;
46
47 ReadStatus status;
48 switch (msg_type) {
49 case kAllocPacketType:
50 status = ParseAlloc();
51 break;
52 case kFreePacketType:
53 status = ParseFree();
54 break;
55 default:
56 return; // TODO(brettw) signal error.
57 }
58 if (status != READ_OK)
59 return; // TODO(brettw) signal error.
60 }
61 }
62
63 void MemlogStreamParser::OnStreamComplete() {
64 receiver_->OnComplete();
65 }
66
67 bool MemlogStreamParser::AreBytesAvailable(size_t count) const {
68 size_t used = 0;
69 size_t current_block_offset = block_zero_offset_;
70 for (auto it = blocks_.begin(); it != blocks_.end() && used < count; ++it) {
71 used += it->size - current_block_offset;
72 current_block_offset = 0;
73 }
74 return used >= count;
75 }
76
77 bool MemlogStreamParser::PeekBytes(size_t count, void* dest) const {
78 char* dest_char = static_cast<char*>(dest);
79 size_t used = 0;
80
81 size_t current_block_offset = block_zero_offset_;
82 for (const auto& block : blocks_) {
83 size_t in_current_block = block.size - current_block_offset;
84 size_t to_copy = std::min(count - used, in_current_block);
85
86 memcpy(&dest_char[used], &block.data[current_block_offset], to_copy);
87 used += to_copy;
88
89 // All subsequent blocks start reading at offset 0.
90 current_block_offset = 0;
91 }
92 return used == count;
93 }
94
95 bool MemlogStreamParser::ReadBytes(size_t count, void* dest) {
96 if (!PeekBytes(count, dest))
97 return false;
98 ConsumeBytes(count);
99 return true;
100 }
101
102 void MemlogStreamParser::ConsumeBytes(size_t count) {
103 DCHECK(AreBytesAvailable(count));
104 while (count > 0) {
105 size_t bytes_left_in_block = blocks_.front().size - block_zero_offset_;
106 if (bytes_left_in_block > count) {
107 // Still data left in this block;
108 block_zero_offset_ += count;
109 return;
110 }
111
112 // Current block is consumed.
113 blocks_.pop_front();
114 block_zero_offset_ = 0;
115 count -= bytes_left_in_block;
116 }
117 }
118
119 MemlogStreamParser::ReadStatus MemlogStreamParser::ParseHeader() {
120 StreamHeader header;
121 if (!ReadBytes(sizeof(StreamHeader), &header))
122 return READ_NO_DATA;
123
124 if (header.signature != kStreamSignature)
125 return READ_ERROR;
126
127 receiver_->OnHeader(header);
128 return READ_OK;
129 }
130
131 MemlogStreamParser::ReadStatus MemlogStreamParser::ParseAlloc() {
132 // Read the packet. Can't commit the read until the stack is read and
133 // that has to be done below.
134 AllocPacket alloc_packet;
135 if (!PeekBytes(sizeof(AllocPacket), &alloc_packet))
136 return READ_NO_DATA;
137
138 std::vector<Address> stack;
139 stack.resize(alloc_packet.stack_len);
140 size_t stack_byte_size = sizeof(Address) * alloc_packet.stack_len;
141
142 if (!AreBytesAvailable(sizeof(AllocPacket) + stack_byte_size))
143 return READ_NO_DATA;
144
145 // Everything will fit, mark packet consumed, read stack.
146 ConsumeBytes(sizeof(AllocPacket));
147 if (!stack.empty())
148 ReadBytes(stack_byte_size, stack.data());
149
150 receiver_->OnAlloc(alloc_packet, std::move(stack));
151 return READ_OK;
152 }
153
154 MemlogStreamParser::ReadStatus MemlogStreamParser::ParseFree() {
155 FreePacket free_packet;
156 if (!ReadBytes(sizeof(FreePacket), &free_packet))
157 return READ_NO_DATA;
158
159 receiver_->OnFree(free_packet);
160 return READ_OK;
161 }
162
163 } // namespace profiling
OLDNEW
« no previous file with comments | « chrome/profiling/memlog_stream_parser.h ('k') | chrome/profiling/profiling_globals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698