// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_TIMER_H_
#define RUNTIME_VM_TIMER_H_

#include "platform/atomic.h"
#include "platform/utils.h"
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/os.h"

namespace dart {

struct MeasureMonotonic {
  static inline int64_t Now() { return OS::GetCurrentMonotonicMicros(); }
};

struct MeasureCpu {
  static inline int64_t Now() { return OS::GetCurrentThreadCPUMicros(); }
};

// Timer class allows timing of specific operations in the VM.
template <typename Measure>
class TimerImpl : public ValueObject {
 public:
  TimerImpl() { Reset(); }
  ~TimerImpl() {}

  // Start timer.
  void Start() {
    start_ = Measure::Now();
    running_ = true;
  }

  // Stop timer.
  void Stop() {
    ASSERT(running());
    stop_ = Measure::Now();
    int64_t elapsed = ElapsedMicros();
    max_contiguous_ = Utils::Maximum(max_contiguous_.load(), elapsed);
    // Make increment atomic in case it occurs in parallel with aggregation.
    total_.fetch_add(elapsed);
    running_ = false;
  }

  // Get total cumulative elapsed time in micros.
  int64_t TotalElapsedTime() const {
    int64_t result = total_;
    if (running_) {
      int64_t now = Measure::Now();
      result += (now - start_);
    }
    return result;
  }

  int64_t MaxContiguous() const {
    int64_t result = max_contiguous_;
    if (running_) {
      int64_t now = Measure::Now();
      result = Utils::Maximum(result, now - start_);
    }
    return result;
  }

  void Reset() {
    start_ = 0;
    stop_ = 0;
    total_ = 0;
    max_contiguous_ = 0;
    running_ = false;
  }

  bool IsReset() const {
    return (start_ == 0) && (stop_ == 0) && (total_ == 0) &&
           (max_contiguous_ == 0) && !running_;
  }

  void AddTotal(const TimerImpl& other) { total_.fetch_add(other.total_); }

  // Accessors.
  bool running() const { return running_; }

 private:
  friend class Timer;

  explicit TimerImpl(int64_t elapsed)
      : total_(elapsed), max_contiguous_(elapsed) {}

  int64_t ElapsedMicros() const { return stop_ - start_; }

  RelaxedAtomic<int64_t> start_;
  RelaxedAtomic<int64_t> stop_;
  RelaxedAtomic<int64_t> total_;
  RelaxedAtomic<int64_t> max_contiguous_;

  bool running_ = false;

  DISALLOW_COPY_AND_ASSIGN(TimerImpl);
};

class Timer : public ValueObject {
 public:
  Timer(int64_t elapsed, int64_t elapsed_cpu)
      : monotonic_(elapsed), cpu_(elapsed) {}
  Timer() { Reset(); }
  ~Timer() {}

  // Start timer.
  void Start() {
    cpu_.Start();
    monotonic_.Start();
  }

  // Stop timer.
  void Stop() {
    cpu_.Stop();
    monotonic_.Stop();
  }

  // Get total cumulative elapsed time in micros.
  int64_t TotalElapsedTime() const { return monotonic_.TotalElapsedTime(); }
  int64_t TotalElapsedTimeCpu() const { return cpu_.TotalElapsedTime(); }

  int64_t MaxContiguous() const { return monotonic_.MaxContiguous(); }

  void Reset() {
    monotonic_.Reset();
    cpu_.Reset();
  }

  bool IsReset() const { return monotonic_.IsReset(); }

  void AddTotal(const Timer& other) {
    monotonic_.AddTotal(other.monotonic_);
    cpu_.AddTotal(other.cpu_);
  }

  const char* FormatElapsedHumanReadable(Zone* zone) const {
    return FormatElapsedHumanReadable(zone, TotalElapsedTime(),
                                      TotalElapsedTimeCpu());
  }

  static const char* FormatTime(Zone* zone, int64_t total) {
    if (total > kMicrosecondsPerSecond) {
      return OS::SCreate(zone, "%6.2f s", MicrosecondsToSeconds(total));
    } else if (total > kMicrosecondsPerMillisecond) {
      return OS::SCreate(zone, "%6.2f ms", MicrosecondsToMilliseconds(total));
    } else {
      return OS::SCreate(zone, "%6" Pd64 " \u00B5s", total);
    }
  }

  static constexpr double kCpuTimeReportingThreshold = 0.05;

  // Formats the given monotonic and CPU times as a human readable string.
  //
  // CPU time is included into the formated string only if
  // it is |kCpuTimeReportingThreshold| percent different from the monotonic
  // time.
  static const char* FormatElapsedHumanReadable(Zone* zone,
                                                int64_t total_elapsed,
                                                int64_t total_elapsed_cpu) {
    if ((total_elapsed == 0) ||
        static_cast<double>(Utils::Abs(total_elapsed - total_elapsed_cpu) /
                            total_elapsed) < kCpuTimeReportingThreshold) {
      return FormatTime(zone, total_elapsed);
    } else {
      return OS::SCreate(zone, "%s (cpu %s)", FormatTime(zone, total_elapsed),
                         FormatTime(zone, total_elapsed_cpu));
    }
  }

 private:
  TimerImpl<MeasureMonotonic> monotonic_;
  TimerImpl<MeasureCpu> cpu_;

  DISALLOW_COPY_AND_ASSIGN(Timer);
};

class TimerScope : public StackResource {
 public:
  TimerScope(ThreadState* thread, Timer* timer)
      : StackResource(thread), timer_(timer) {
    if (timer_ != nullptr) timer_->Start();
  }
  ~TimerScope() {
    if (timer_ != nullptr) timer_->Stop();
  }

 private:
  Timer* const timer_;
};

class PrintTimeScope : public ValueObject {
 public:
  explicit PrintTimeScope(const char* name) : name_(name) { timer_.Start(); }
  ~PrintTimeScope();

 private:
  Timer timer_;
  const char* name_;
};

}  // namespace dart

#endif  // RUNTIME_VM_TIMER_H_
