// Copyright 2018 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. 'use strict'; export class Isolate { constructor(address) { this.address = address; this.start = null; this.end = null; this.samples = Object.create(null); this.non_empty_instance_types = new Set(); this.gcs = Object.create(null); this.zonetags = []; this.samples = {zone: {}}; this.data_sets = new Set(); this.peakMemory = 0; // Maps instance_types to their max memory consumption over all gcs. this.instanceTypePeakMemory = Object.create(null); // Peak memory consumed by any single instance type. this.singleInstanceTypePeakMemory = 0; } finalize() { Object.values(this.gcs).forEach(gc => this.finalizeGC(gc)); this.sortInstanceTypePeakMemory(); } getLabel() { let label = `${this.address}: gc=#${Object.keys(this.gcs).length}`; label += ` peak=${formatBytes(this.peakMemory)}` return label; } finalizeGC(gc_data) { this.data_sets.forEach(key => this.finalizeDataSet(gc_data[key])); if (!('live' in gc_data)) return; let liveData = gc_data.live; this.peakMemory = Math.max(this.peakMemory, liveData.overall); let data = liveData.instance_type_data; for (let name in data) { let prev = this.instanceTypePeakMemory[name] || 0; this.instanceTypePeakMemory[name] = Math.max(prev, data[name].overall); } } finalizeDataSet(data_set) { // Create a ranked instance type array that sorts instance types by // memory size (overall). let data = data_set.instance_type_data; let ranked_instance_types = [...data_set.non_empty_instance_types].sort((a, b) => { return data[a].overall - data[b].overall; }); // Reassemble the instance_type list sorted by size. let sorted_data = Object.create(null); let max = 0; ranked_instance_types.forEach((name) => { let entry = sorted_data[name] = data[name]; max = Math.max(max, entry.overall); }); data_set.instance_type_data = data; data_set.singleInstancePeakMemory = max; Object.entries(data_set.instance_type_data).forEach(([name, entry]) => { this.checkHistogram( name, entry, data_set.bucket_sizes, 'histogram', ' overall'); this.checkHistogram( name, entry, data_set.bucket_sizes, 'over_allocated_histogram', ' over_allocated'); }); } // Check that a lower bound for histogram memory does not exceed the // overall counter. checkHistogram(type, entry, bucket_sizes, histogram, overallProperty) { let sum = 0; for (let i = 1; i < entry[histogram].length; i++) { sum += entry[histogram][i] * bucket_sizes[i - 1]; } const overall = entry[overallProperty]; if (sum >= overall) { console.error( `${type}: sum('${histogram}') > overall (${sum} > ${overall})`); } } sortInstanceTypePeakMemory() { let entries = Object.entries(this.instanceTypePeakMemory); entries.sort((a, b) => {return b[1] - a[1]}); this.instanceTypePeakMemory = Object.create(null); let max = 0; for (let [key, value] of entries) { this.instanceTypePeakMemory[key] = value; max = Math.max(max, value); } this.singleInstanceTypePeakMemory = max; } getInstanceTypePeakMemory(type) { if (!(type in this.instanceTypePeakMemory)) return 0; return this.instanceTypePeakMemory[type]; } }