[heap-profiler] Allow intermediate sampling heap profile retrieval during recording.

The sampling heap profiles can now be retrieved without stopping
the profiler.

BUG=v8:6887

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I491206d0bafd7d4e198622117c12aab0057e6bc6
Reviewed-on: https://chromium-review.googlesource.com/749700
Reviewed-by: Pavel Feldman <pfeldman@chromium.org>
Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Commit-Queue: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49160}
This commit is contained in:
Alexei Filippov 2017-11-02 10:47:27 -07:00 committed by Commit Bot
parent c82cd31325
commit 3989b5c84a
5 changed files with 76 additions and 6 deletions

View File

@ -1144,6 +1144,12 @@
"returns": [
{ "name": "profile", "$ref": "SamplingHeapProfile", "description": "Recorded sampling heap profile." }
]
},
{
"name": "getSamplingProfile",
"returns": [
{ "name": "profile", "$ref": "SamplingHeapProfile", "description": "Return the sampling profile being collected." }
]
}
],
"events": [

View File

@ -363,17 +363,24 @@ buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node) {
Response V8HeapProfilerAgentImpl::stopSampling(
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) {
Response result = getSamplingProfile(profile);
if (result.isSuccess()) {
m_isolate->GetHeapProfiler()->StopSamplingHeapProfiler();
m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled,
false);
}
return result;
}
Response V8HeapProfilerAgentImpl::getSamplingProfile(
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) {
v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
if (!profiler) return Response::Error("Cannot access v8 heap profiler");
v8::HandleScope scope(
m_isolate); // Allocation profile contains Local handles.
m_isolate); // v8::AllocationProfile contains Local handles.
std::unique_ptr<v8::AllocationProfile> v8Profile(
profiler->GetAllocationProfile());
profiler->StopSamplingHeapProfiler();
m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled,
false);
if (!v8Profile)
return Response::Error("Cannot access v8 sampled heap profile.");
return Response::Error("V8 sampling heap profiler was not started.");
v8::AllocationProfile::Node* root = v8Profile->GetRootNode();
*profile = protocol::HeapProfiler::SamplingHeapProfile::create()
.setHead(buildSampingHeapProfileNode(root))

View File

@ -46,6 +46,8 @@ class V8HeapProfilerAgentImpl : public protocol::HeapProfiler::Backend {
Response startSampling(Maybe<double> samplingInterval) override;
Response stopSampling(
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>*) override;
Response getSamplingProfile(
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>*) override;
private:
void startTrackingHeapObjectsInternal(bool trackAllocations);

View File

@ -0,0 +1,7 @@
Checks sampling heap profiler methods.
Expected error: V8 sampling heap profiler was not started.
Allocated size is zero in the beginning: true
Allocated size is more than 100KB after a chunk is allocated: true
Allocated size increased after one more chunk is allocated: true
Allocated size did not change after stopping: true
Successfully finished

View File

@ -0,0 +1,48 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --sampling-heap-profiler-suppress-randomness
(async function() {
let {contextGroup, Protocol} = InspectorTest.start('Checks sampling heap profiler methods.');
contextGroup.addScript(`
var holder = [];
function allocateChunk() {
holder.push(new Array(100000).fill(42));
}
//# sourceURL=test.js`);
Protocol.HeapProfiler.enable();
const profile0 = await Protocol.HeapProfiler.getSamplingProfile();
InspectorTest.log('Expected error: ' + profile0.error.message);
await Protocol.HeapProfiler.startSampling();
const profile1 = await Protocol.HeapProfiler.getSamplingProfile();
const size1 = nodeSize(profile1.result.profile.head);
InspectorTest.log('Allocated size is zero in the beginning:', size1 === 0);
await Protocol.Runtime.evaluate({ expression: 'allocateChunk()' });
const profile2 = await Protocol.HeapProfiler.getSamplingProfile();
const size2 = nodeSize(profile2.result.profile.head);
InspectorTest.log('Allocated size is more than 100KB after a chunk is allocated:', size2 > 100000);
await Protocol.Runtime.evaluate({ expression: 'allocateChunk()' });
const profile3 = await Protocol.HeapProfiler.getSamplingProfile();
const size3 = nodeSize(profile3.result.profile.head);
InspectorTest.log('Allocated size increased after one more chunk is allocated:', size3 > size2);
const profile4 = await Protocol.HeapProfiler.stopSampling();
const size4 = nodeSize(profile4.result.profile.head);
InspectorTest.log('Allocated size did not change after stopping:', size4 === size3);
InspectorTest.log('Successfully finished');
InspectorTest.completeTest();
function nodeSize(node) {
return node.children.reduce((res, child) => res + nodeSize(child),
node.callFrame.functionName === 'allocateChunk' ? node.selfSize : 0);
}
})();