// Copyright 2015 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 "base/threading/thread.h"
#include "build/build_config.h"
#include "cobalt/trace_event/benchmark.h"

#if defined(OS_STARBOARD)
#include "starboard/thread.h"
#define usleep(usec) SbThreadSleep(usec)
#endif

// A sample simple benchmark that tracks only a single event, in this case,
// "LoopIteration".
TRACE_EVENT_BENCHMARK1(
    SampleTestBenchmarkWithOneTrackedEvent,
    "LoopIteration", cobalt::trace_event::IN_SCOPE_DURATION) {
  const int kRenderIterationCount = 40;
  for (int i = 0; i < kRenderIterationCount; ++i) {
    TRACE_EVENT0("SampleBenchmark", "LoopIteration");
    {
      TRACE_EVENT0("SampleBenchmark", "SubEventA");
      usleep(10000);
    }
    {
      TRACE_EVENT0("SampleBenchmark", "SubEventB");
      usleep(20000);
    }
  }
}

// This sample benchmark is very similar to the single event tracking benchmark
// above, however it tracks 3 events instead of 1.  For one of those 3 events,
// "SubEventA", we track both its in-scope duration as well as the time between
// subsequent event instance start times.
TRACE_EVENT_BENCHMARK4(
    SampleTestBenchmarkWithThreeTrackedEvents,
    "LoopIteration", cobalt::trace_event::IN_SCOPE_DURATION,
    "SubEventA", cobalt::trace_event::IN_SCOPE_DURATION,
    "SubEventA", cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS,
    "SubEventB", cobalt::trace_event::IN_SCOPE_DURATION) {
  const int kRenderIterationCount = 40;
  for (int i = 0; i < kRenderIterationCount; ++i) {
    TRACE_EVENT0("SampleBenchmark", "LoopIteration");
    {
      TRACE_EVENT0("SampleBenchmark", "SubEventA");
      usleep(10000);
    }
    {
      TRACE_EVENT0("SampleBenchmark", "SubEventB");
      usleep(20000);
    }
  }
}

// The following example demonstrates that the benchmarking system will track
// over flow/thread boundaries.  Since "FlowInitiator"'s duration will always
// include the "HandleTask()" event as a child, "FlowInitiator"'s duration will
// always be greater than "HandleTask()"'s.  In fact, as the worker thread
// gets more and more backed up dealing with HandleTask() tasks (which are
// being produced faster than they can be consumed), the time between when
// "FlowInitiator" starts and "HandleTask()" ends will increase as the
// test continues.
void HandleTask() {
  TRACE_EVENT0("SampleBenchmark", "HandleTask()");
  usleep(10000);
}

TRACE_EVENT_BENCHMARK4(
    FlowExample,
    "FlowInitiator", cobalt::trace_event::IN_SCOPE_DURATION,
    "FlowInitiator", cobalt::trace_event::FLOW_DURATION,
    "FlowInitiator", cobalt::trace_event::TIME_BETWEEN_EVENT_STARTS,
    "HandleTask()", cobalt::trace_event::FLOW_DURATION) {
  base::Thread thread("Worker");
  thread.Start();

  const int kRenderIterationCount = 40;
  for (int i = 0; i < kRenderIterationCount; ++i) {
    usleep(2000);
    TRACE_EVENT0("SampleBenchmark", "FlowInitiator");
    thread.message_loop()->PostTask(FROM_HERE, base::Bind(&HandleTask));
    usleep(5000);
  }
}

// A sample full benchmark where we have the ability to specify the analysis
// method (allowing for sophisticated metrics to be extracted) as well as
// the results compilation method which decides how to present the data
// to subsequent stages of the pipeline.
class SampleTestAdvancedBenchmark : public cobalt::trace_event::Benchmark {
 public:
  // This method will be executed in order to generate the trace results
  // that will subsequently be analyzed.
  void Experiment() OVERRIDE {
    const int kRenderIterationCount = 100;
    for (int i = 0; i < kRenderIterationCount; ++i) {
      TRACE_EVENT0("SampleBenchmark", "LoopIteration");
      {
        TRACE_EVENT0("SampleBenchmark", "SubEventA");
        usleep(10000);
      }
      {
        TRACE_EVENT0("SampleBenchmark", "SubEventB");
        usleep(20000);
      }
    }
  }

  // This method is called to allow the benchmark to handle a trace event
  // occurring.  This occurs when a TRACE_EVENT or TRACE_EVENT_FLOW
  // call from above completes and all its child events and flows have also
  // completed.
  void AnalyzeTraceEvent(const scoped_refptr<
      cobalt::trace_event::EventParser::ScopedEvent>& event) OVERRIDE {
    if (event->name() == "LoopIteration") {
      if (event->flow_duration()) {
        loop_iteration_times_in_seconds_.push_back(
            event->flow_duration()->InSecondsF());
      }
    } else if (event->name() == "SubEventA") {
      if (event->flow_duration()) {
        sub_event_a_times_in_seconds_.push_back(
            event->flow_duration()->InSecondsF());
      }
    } else if (event->name() == "SubEventB") {
      if (event->flow_duration()) {
        sub_event_b_times_in_seconds_.push_back(
            event->flow_duration()->InSecondsF());
      }
    }
  }

  // This is called after all events have been analyzed and it is time to
  // produce results.  All Result objects returned will be output as separate
  // variables.
  std::vector<Result> CompileResults() OVERRIDE {
    std::vector<Result> results;

    results.push_back(Result("LoopIteration time in seconds",
                             loop_iteration_times_in_seconds_));
    results.push_back(
        Result("SubEventA time in seconds", sub_event_a_times_in_seconds_));
    results.push_back(
        Result("SubEventB time in seconds", sub_event_b_times_in_seconds_));

    return results;
  }

 private:
  std::vector<double> loop_iteration_times_in_seconds_;
  std::vector<double> sub_event_a_times_in_seconds_;
  std::vector<double> sub_event_b_times_in_seconds_;
};
TRACE_EVENT_REGISTER_BENCHMARK(SampleTestAdvancedBenchmark);
