[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:
parent
c82cd31325
commit
3989b5c84a
@ -1144,6 +1144,12 @@
|
|||||||
"returns": [
|
"returns": [
|
||||||
{ "name": "profile", "$ref": "SamplingHeapProfile", "description": "Recorded sampling heap profile." }
|
{ "name": "profile", "$ref": "SamplingHeapProfile", "description": "Recorded sampling heap profile." }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "getSamplingProfile",
|
||||||
|
"returns": [
|
||||||
|
{ "name": "profile", "$ref": "SamplingHeapProfile", "description": "Return the sampling profile being collected." }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"events": [
|
"events": [
|
||||||
|
@ -363,17 +363,24 @@ buildSampingHeapProfileNode(const v8::AllocationProfile::Node* node) {
|
|||||||
|
|
||||||
Response V8HeapProfilerAgentImpl::stopSampling(
|
Response V8HeapProfilerAgentImpl::stopSampling(
|
||||||
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) {
|
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();
|
v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler();
|
||||||
if (!profiler) return Response::Error("Cannot access v8 heap profiler");
|
|
||||||
v8::HandleScope scope(
|
v8::HandleScope scope(
|
||||||
m_isolate); // Allocation profile contains Local handles.
|
m_isolate); // v8::AllocationProfile contains Local handles.
|
||||||
std::unique_ptr<v8::AllocationProfile> v8Profile(
|
std::unique_ptr<v8::AllocationProfile> v8Profile(
|
||||||
profiler->GetAllocationProfile());
|
profiler->GetAllocationProfile());
|
||||||
profiler->StopSamplingHeapProfiler();
|
|
||||||
m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled,
|
|
||||||
false);
|
|
||||||
if (!v8Profile)
|
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();
|
v8::AllocationProfile::Node* root = v8Profile->GetRootNode();
|
||||||
*profile = protocol::HeapProfiler::SamplingHeapProfile::create()
|
*profile = protocol::HeapProfiler::SamplingHeapProfile::create()
|
||||||
.setHead(buildSampingHeapProfileNode(root))
|
.setHead(buildSampingHeapProfileNode(root))
|
||||||
|
@ -46,6 +46,8 @@ class V8HeapProfilerAgentImpl : public protocol::HeapProfiler::Backend {
|
|||||||
Response startSampling(Maybe<double> samplingInterval) override;
|
Response startSampling(Maybe<double> samplingInterval) override;
|
||||||
Response stopSampling(
|
Response stopSampling(
|
||||||
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>*) override;
|
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>*) override;
|
||||||
|
Response getSamplingProfile(
|
||||||
|
std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>*) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startTrackingHeapObjectsInternal(bool trackAllocations);
|
void startTrackingHeapObjectsInternal(bool trackAllocations);
|
||||||
|
@ -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
|
48
test/inspector/heap-profiler/sampling-heap-profiler.js
Normal file
48
test/inspector/heap-profiler/sampling-heap-profiler.js
Normal 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);
|
||||||
|
}
|
||||||
|
})();
|
Loading…
Reference in New Issue
Block a user