v8/tools/heap-layout/trace-file-reader.mjs
JianxiaoLuIntel 257b0a43ac [tool] heap layout trace file visualization tool
Design doc:
https://docs.google.com/document/d/1rxM3sDd-ZiOLznqw7MvYraulAPWJSVqC_CztO4YpUTQ/edit

Change-Id: I471ff31f32b7bdd22cb03005c1dcc18aa485ad77
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3313793
Auto-Submit: Jianxiao Lu <jianxiao.lu@intel.com>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Shiyu Zhang <shiyu.zhang@intel.com>
Cr-Commit-Position: refs/heads/main@{#78428}
2021-12-22 02:07:35 +00:00

111 lines
3.2 KiB
JavaScript

// Copyright 2021 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.
import {calcOffsetInVMCage} from '../js/helper.mjs';
import {DOM, FileReader,} from '../js/web-api-helper.mjs';
import {kSpaceNames} from './space-categories.mjs';
class TraceLogParseHelper {
static re_gc_header = /(Before|After) GC:\d/;
static re_page_info =
/\{owner:.+,address:.+,size:.+,allocated_bytes:.+,wasted_memory:.+\}/;
static re_owner = /(?<=owner:)[a-z_]+_space/;
static re_address = /(?<=address:)0x[a-f0-9]+(?=,)/;
static re_size = /(?<=size:)\d+(?=,)/;
static re_allocated_bytes = /(?<=allocated_bytes:)\d+(?=,)/;
static re_wasted_memory = /(?<=wasted_memory:)\d+(?=})/;
static matchGCHeader(content) {
return this.re_gc_header.test(content);
}
static matchPageInfo(content) {
return this.re_page_info.test(content);
}
static parsePageInfo(content) {
const owner = this.re_owner.exec(content)[0];
const address =
calcOffsetInVMCage(BigInt(this.re_address.exec(content)[0], 16));
const size = parseInt(this.re_size.exec(content)[0]);
const allocated_bytes = parseInt(this.re_allocated_bytes.exec(content)[0]);
const wasted_memory = parseInt(this.re_wasted_memory.exec(content)[0]);
const info = [
owner,
address,
address + size,
allocated_bytes,
wasted_memory,
];
return info;
}
// Create a empty snapshot.
static createSnapShotData() {
let snapshot = {header: null, data: {}};
for (let space_name of kSpaceNames) {
snapshot.data[space_name] = [];
}
return snapshot;
}
static createModelFromV8TraceFile(contents) {
let snapshots = [];
let snapshot = this.createSnapShotData();
// Fill data info a snapshot, then push it into snapshots.
for (let content of contents) {
if (this.matchGCHeader(content)) {
if (snapshot.header != null) {
snapshots.push(snapshot);
}
snapshot = this.createSnapShotData();
snapshot.header = content;
continue;
}
if (this.matchPageInfo(content)) {
let pageinfo = this.parsePageInfo(content);
try {
snapshot.data[pageinfo[0]].push(pageinfo);
} catch (e) {
console.error(e);
}
}
}
// EOL, push the last.
if (snapshot.header != null) {
snapshots.push(snapshot);
}
return snapshots;
}
}
DOM.defineCustomElement('../js/log-file-reader', 'trace-file-reader',
(templateText) =>
class TraceFileReader extends FileReader {
constructor() {
super(templateText);
this.fullDataFromFile = '';
this.addEventListener('fileuploadchunk', (e) => this.handleLoadChunk(e));
this.addEventListener('fileuploadend', (e) => this.handleLoadEnd(e));
}
handleLoadChunk(event) {
this.fullDataFromFile += event.detail;
}
handleLoadEnd(event) {
let contents = this.fullDataFromFile.split('\n');
let snapshots = TraceLogParseHelper.createModelFromV8TraceFile(contents);
this.dispatchEvent(new CustomEvent('change', {
bubbles: true,
composed: true,
detail: snapshots,
}));
}
});