drawChart()

in frontend/app/components/memory_profile/memory_timeline_graph/memory_timeline_graph.ts [44:158]


  drawChart() {
    if (!this.chartRef || !this.chart || this.memoryId === '' ||
        !this.memoryProfileProtoOrNull ||
        !this.memoryProfileProtoOrNull.memoryProfilePerAllocator) {
      return;
    }

    this.width =
        Math.min(MAX_CHART_WIDTH, this.chartRef.nativeElement.offsetWidth);

    const snapshots =
        this.memoryProfileProtoOrNull.memoryProfilePerAllocator[this.memoryId]
            .memoryProfileSnapshots;

    if (!snapshots) return;
    snapshots.sort((a, b) => Number(a.timeOffsetPs) - Number(b.timeOffsetPs));

    // CPU allocator does not provide the free memory bytes stats, in this case,
    // do not display the free memory line in timeline graph.
    let hasFreeMemoryData = false;
    for (let i = 0; i < snapshots.length; i++) {
      const stats = snapshots[i].aggregationStats;
      if (stats && stats.freeMemoryBytes !== '0') {
        hasFreeMemoryData = true;
        break;
      }
    }

    const dataTable = new google.visualization.DataTable();
    dataTable.addColumn('number', 'timestamp(ps)');
    dataTable.addColumn('number', 'stack');
    dataTable.addColumn('number', 'heap');
    dataTable.addColumn({type: 'string', role: 'tooltip'});
    if (hasFreeMemoryData) {
      dataTable.addColumn('number', 'free');
    }
    dataTable.addColumn('number', 'fragmentation');

    for (let i = 0; i < snapshots.length; i++) {
      const stats = snapshots[i].aggregationStats;
      if (!stats || !snapshots[i].timeOffsetPs) {
        continue;
      }
      const row = [
        this.picoToMilli(snapshots[i].timeOffsetPs),
        this.bytesToGiBs(stats.stackReservedBytes),
        this.bytesToGiBs(stats.heapAllocatedBytes),
        this.getMetadataTooltip(snapshots[i])
      ];
      if (hasFreeMemoryData) {
        row.push(this.bytesToGiBs(stats.freeMemoryBytes));
      }
      row.push((stats.fragmentation || 0) * 100);
      dataTable.addRow(row);
    }


    const fragmentationProperty = {
      'targetAxisIndex': 1,  // Using string parameter to prevent renaming.
      type: 'line',
      lineDashStyle: [4, 4],
    };
    const lineProperty = {'targetAxisIndex': 0};
    const seriesWithFreeMemory = {
      0: lineProperty,
      1: lineProperty,
      2: lineProperty,
      3: fragmentationProperty,
    };
    const seriesWithoutFreeMemory = {
      0: lineProperty,
      1: lineProperty,
      2: fragmentationProperty,
    };


    const options = {
      curveType: 'none',
      chartArea: {left: 60, right: 60, width: '100%'},
      hAxis: {
        title: 'Timestamp (ms)',
        textStyle: {bold: true},
      },
      vAxes: {
        0: {
          title: 'Memory Usage (GiBs)',
          minValue: 0,
          textStyle: {bold: true},
        },
        1: {
          title: 'Fragmentation (%)',
          minValue: 0,
          maxValue: 100,
          textStyle: {bold: true},
        },
      },
      series: hasFreeMemoryData ? seriesWithFreeMemory :
                                  seriesWithoutFreeMemory,
      // tslint:disable-next-line:no-any
      legend: {position: 'top' as any},
      tooltip: {
        trigger: 'selection',
      },
      colors: ['red', 'orange', 'green'],
      height: this.height,
      isStacked: true,
      explorer: {
        actions: ['dragToZoom', 'rightClickToReset'],
        maxZoomIn: .001,
        maxZoomOut: 10,
      },
    };
    this.chart.draw(
        dataTable, options as google.visualization.AreaChartOptions);
  }