// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/browser/memory_tracker/tool/malloc_stats_tool.h"

#include <string>
#include <vector>

#include "cobalt/browser/memory_tracker/tool/histogram_table_csv_base.h"
#include "cobalt/browser/memory_tracker/tool/params.h"
#include "cobalt/browser/memory_tracker/tool/tool_impl.h"
#include "nb/analytics/memory_tracker.h"
#include "starboard/string.h"
#include "starboard/types.h"

namespace cobalt {
namespace browser {
namespace memory_tracker {

MallocStatsTool::MallocStatsTool() {
}

std::string MallocStatsTool::tool_name() const  {
  return "MallocStatsTool";
}

void MallocStatsTool::Run(Params* params) {
  params->logger()->Output("MallocStatsTool running...\n");

  Timer output_timer(base::TimeDelta::FromSeconds(30));
  Timer sample_timer(base::TimeDelta::FromMilliseconds(50));

  MemoryBytesHistogramCSV histogram_table;
  histogram_table.set_title("Malloc Stats");

  // If we get a finish signal then this will break out of the loop.
  while (!params->wait_for_finish_signal(250 * kSbTimeMillisecond)) {
    // LOG CSV.
    if (output_timer.UpdateAndIsExpired()) {
      std::stringstream ss;
      ss << kNewLine << histogram_table.ToString() << kNewLine << kNewLine;
      params->logger()->Output(ss.str());
    }

    // ADD A HISTOGRAM SAMPLE.
    if (sample_timer.UpdateAndIsExpired()) {
      // Take a sample.
      nb::analytics::MemoryStats memory_stats =
          nb::analytics::GetProcessMemoryStats();

      histogram_table.BeginRow(params->time_since_start());
      histogram_table.AddRowValue(
          "TotalCpuMemory(MB)", memory_stats.total_cpu_memory);
      histogram_table.AddRowValue(
          "UsedCpuMemory(MB)", memory_stats.used_cpu_memory);
      histogram_table.AddRowValue(
          "TotalGpuMemory(MB)", memory_stats.total_gpu_memory);
      histogram_table.AddRowValue(
          "UsedGpuMemory(MB)", memory_stats.used_gpu_memory);
      histogram_table.FinalizeRow();
    }

    // COMPRESS TABLE WHEN FULL.
    //
    // Table is full, therefore eliminate half of the elements.
    // Reduce sample frequency to match.
    if (histogram_table.NumberOfRows() >= 100) {
      // Compression step.
      histogram_table.RemoveOddElements();

      // By double the sampling time this keeps the table linear with
      // respect to time. If sampling time was not doubled then there
      // would be time distortion in the graph.
      sample_timer.ScaleTriggerTime(2.0);
      sample_timer.Restart();
    }
  }
}

}  // namespace memory_tracker
}  // namespace browser
}  // namespace cobalt
