| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <link rel="import" href="/core/trace_model/timed_event.html"> |
| <link rel="import" href="/core/analysis/util.html"> |
| |
| <script> |
| 'use strict'; |
| |
| /** |
| * @fileoverview Provides the ProcessMemoryDump class. |
| */ |
| tv.exportTo('tv.c.trace_model', function() { |
| /** |
| * The ProcessMemoryDump represents a memory dump of a single process. |
| * @constructor |
| */ |
| function ProcessMemoryDump(globalMemoryDump, process, start) { |
| tv.c.trace_model.TimedEvent.call(this, start); |
| this.process = process; |
| this.globalMemoryDump = globalMemoryDump; |
| |
| this.totalResidentBytes = undefined; |
| this.vmRegions_ = undefined; |
| this.memoryAllocatorDumps_ = undefined; |
| this.memoryAllocatorDumpsByFullName_ = undefined; |
| }; |
| |
| ProcessMemoryDump.prototype = { |
| __proto__: tv.c.trace_model.TimedEvent.prototype, |
| |
| shiftTimestampsForward: function(amount) { |
| this.start += amount; |
| }, |
| |
| get userFriendlyName() { |
| return 'Process memory dump at ' + tv.c.analysis.tsString(this.start); |
| }, |
| |
| get vmRegions() { |
| throw new Error( |
| 'VM regions must be accessed through the mostRecentVmRegions field'); |
| }, |
| |
| set vmRegions(vmRegions) { |
| this.vmRegions_ = vmRegions; |
| }, |
| |
| get memoryAllocatorDumps() { |
| return this.memoryAllocatorDumps_; |
| }, |
| |
| set memoryAllocatorDumps(memoryAllocatorDumps) { |
| this.memoryAllocatorDumps_ = memoryAllocatorDumps; |
| |
| // Clear the index and generate it lazily. |
| this.memoryAllocatorDumpsByFullName_ = undefined; |
| }, |
| |
| getMemoryAllocatorDumpByFullName: function(fullName) { |
| if (this.memoryAllocatorDumps_ === undefined) |
| return undefined; |
| |
| if (this.memoryAllocatorDumpsByFullName_ === undefined) { |
| var index = {}; |
| function addDumpsToIndex(dumps) { |
| dumps.forEach(function(dump) { |
| index[dump.fullName] = dump; |
| addDumpsToIndex(dump.children); |
| }); |
| }; |
| addDumpsToIndex(this.memoryAllocatorDumps_); |
| this.memoryAllocatorDumpsByFullName_ = index; |
| } |
| |
| return this.memoryAllocatorDumpsByFullName_[fullName]; |
| }, |
| |
| get memoryAllocatorDumpsByFullName() { |
| return this.memoryAllocatorDumpsByFullName_; |
| }, |
| |
| getMostRecentTotalVmRegionStat_: function(statGetterFn) { |
| if (this.mostRecentVmRegions === undefined) |
| return undefined; |
| |
| var total = 0; |
| this.mostRecentVmRegions.forEach(function(vmRegion) { |
| total += statGetterFn(vmRegion); |
| }); |
| return total; |
| }, |
| |
| get mostRecentTotalProportionalResidentSizeInBytes() { |
| return this.getMostRecentTotalVmRegionStat_(function(vmRegion) { |
| return vmRegion.byteStats.proportionalResident; |
| }); |
| }, |
| |
| get mostRecentTotalPrivateResidentSizeInBytes() { |
| return this.getMostRecentTotalVmRegionStat_(function(vmRegion) { |
| return vmRegion.byteStats.privateResident; |
| }); |
| }, |
| |
| get mostRecentTotalSharedResidentSizeInBytes() { |
| return this.getMostRecentTotalVmRegionStat_(function(vmRegion) { |
| return vmRegion.byteStats.sharedResident; |
| }); |
| } |
| }; |
| |
| ProcessMemoryDump.hookUpMostRecentVmRegionsLinks = function(processDumps) { |
| var mostRecentVmRegions = undefined; |
| |
| processDumps.forEach(function(processDump) { |
| // Update the most recent VM regions from the current dump. |
| if (processDump.vmRegions_ !== undefined) |
| mostRecentVmRegions = processDump.vmRegions_; |
| |
| // Set the most recent VM regions of the current dump. |
| processDump.mostRecentVmRegions = mostRecentVmRegions; |
| }); |
| }; |
| |
| /** |
| * @constructor |
| */ |
| function MemoryAllocatorDump(fullName, opt_parent) { |
| this.fullName = fullName; |
| this.parent = opt_parent; |
| this.children = []; |
| this.attributes = {}; |
| }; |
| |
| MemoryAllocatorDump.prototype = { |
| get name() { |
| return this.fullName.substring(this.fullName.lastIndexOf('/') + 1); |
| }, |
| |
| addAttribute: function(name, value) { |
| if (name in this.attributes) |
| throw new Error('Duplicate attribute name: ' + name + '.'); |
| this.attributes[name] = value; |
| }, |
| |
| aggregateAttributes: function(opt_model) { |
| var attributes = {}; |
| |
| this.children.forEach(function(child) { |
| child.aggregateAttributes(opt_model); |
| tv.b.iterItems(child.attributes, function(name) { |
| attributes[name] = true; |
| }, this); |
| }, this); |
| |
| tv.b.iterItems(attributes, function(name) { |
| var childAttributes = this.children.map(function(child) { |
| return child.attributes[name]; |
| }, this); |
| var currentAttribute = this.attributes[name]; |
| this.attributes[name] = tv.c.trace_model.Attribute.aggregate( |
| childAttributes, currentAttribute, opt_model); |
| }, this); |
| } |
| }; |
| |
| /** |
| * @constructor |
| */ |
| function VMRegion(startAddress, sizeInBytes, protectionFlags, |
| mappedFile, byteStats) { |
| this.startAddress = startAddress; |
| this.sizeInBytes = sizeInBytes; |
| this.protectionFlags = protectionFlags; |
| this.mappedFile = mappedFile; |
| this.byteStats = byteStats; |
| }; |
| |
| VMRegion.PROTECTION_FLAG_READ = 4; |
| VMRegion.PROTECTION_FLAG_WRITE = 2; |
| VMRegion.PROTECTION_FLAG_EXECUTE = 1; |
| |
| VMRegion.prototype = { |
| get protectionFlagsToString() { |
| return ( |
| (this.protectionFlags & VMRegion.PROTECTION_FLAG_READ ? 'r' : '-') + |
| (this.protectionFlags & VMRegion.PROTECTION_FLAG_WRITE ? 'w' : '-') + |
| (this.protectionFlags & VMRegion.PROTECTION_FLAG_EXECUTE ? 'x' : '-') |
| ); |
| } |
| }; |
| |
| VMRegion.fromDict = function(dict) { |
| return new VMRegion( |
| dict.startAddress, |
| dict.sizeInBytes, |
| dict.protectionFlags, |
| dict.mappedFile, |
| VMRegionByteStats.fromDict(dict.byteStats)); |
| }; |
| |
| /** |
| * @constructor |
| */ |
| function VMRegionByteStats(privateResident, sharedResident, |
| proportionalResident) { |
| this.privateResident = privateResident; |
| this.sharedResident = sharedResident; |
| this.proportionalResident = proportionalResident; |
| }; |
| |
| VMRegionByteStats.prototype = { |
| get totalResident() { |
| return this.privateResident + this.sharedResident; |
| } |
| }; |
| |
| VMRegionByteStats.fromDict = function(dict) { |
| return new VMRegionByteStats( |
| dict.privateResident, |
| dict.sharedResident, |
| dict.proportionalResident); |
| }; |
| |
| tv.c.trace_model.EventRegistry.register( |
| ProcessMemoryDump, |
| { |
| name: 'processMemoryDump', |
| pluralName: 'processMemoryDumps', |
| singleViewElementName: 'tv-c-single-process-memory-dump-sub-view', |
| multiViewElementName: 'tv-c-multi-process-memory-dump-sub-view' |
| }); |
| |
| return { |
| ProcessMemoryDump: ProcessMemoryDump, |
| MemoryAllocatorDump: MemoryAllocatorDump, |
| VMRegion: VMRegion, |
| VMRegionByteStats: VMRegionByteStats |
| }; |
| }); |
| </script> |