80 lines
2.5 KiB
C
80 lines
2.5 KiB
C
|
// Copyright 2004-present Facebook. All Rights Reserved.
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <atomic>
|
||
|
#include <thread>
|
||
|
|
||
|
// #define WITH_MICRO_PROFILER 1
|
||
|
|
||
|
#ifdef WITH_MICRO_PROFILER
|
||
|
#define MICRO_PROFILER_SECTION(name) MicroProfilerSection __b(name)
|
||
|
#define MICRO_PROFILER_SECTION_NAMED(var_name, name) MicroProfilerSection var_name(name)
|
||
|
#else
|
||
|
#define MICRO_PROFILER_SECTION(name)
|
||
|
#define MICRO_PROFILER_SECTION_NAMED(var_name, name)
|
||
|
#endif
|
||
|
|
||
|
namespace facebook {
|
||
|
namespace react {
|
||
|
|
||
|
enum MicroProfilerName {
|
||
|
__INTERNAL_BENCHMARK_INNER,
|
||
|
__INTERNAL_BENCHMARK_OUTER,
|
||
|
__LENGTH__,
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* MicroProfiler is a performance profiler for measuring the cumulative impact of
|
||
|
* a large number of small-ish calls. This is normally a problem for standard profilers
|
||
|
* like Systrace because the overhead of the profiler itself skews the timings you
|
||
|
* are able to collect. This is especially a problem when doing nested calls to
|
||
|
* profiled functions, as the parent calls will contain the overhead of their profiling
|
||
|
* plus the overhead of all their childrens' profiling.
|
||
|
*
|
||
|
* MicroProfiler attempts to be low overhead by 1) aggregating timings in memory and
|
||
|
* 2) trying to remove estimated profiling overhead from the returned timings.
|
||
|
*
|
||
|
* To remove estimated overhead, at the beginning of each trace we calculate the
|
||
|
* average cost of profiling a no-op code section, as well as invoking the average
|
||
|
* cost of invoking the system clock. The former is subtracted out for each child
|
||
|
* profiler section that is invoked within a parent profiler section. The latter is
|
||
|
* subtracted from each section, child or not.
|
||
|
*
|
||
|
* After MicroProfiler::stopProfiling() is called, a table of tracing data is emitted
|
||
|
* to glog (which shows up in logcat on Android).
|
||
|
*/
|
||
|
struct MicroProfiler {
|
||
|
static const char* profilingNameToString(MicroProfilerName name) {
|
||
|
switch (name) {
|
||
|
case __INTERNAL_BENCHMARK_INNER:
|
||
|
return "__INTERNAL_BENCHMARK_INNER";
|
||
|
case __INTERNAL_BENCHMARK_OUTER:
|
||
|
return "__INTERNAL_BENCHMARK_OUTER";
|
||
|
case __LENGTH__:
|
||
|
throw std::runtime_error("__LENGTH__ has no name");
|
||
|
default:
|
||
|
throw std::runtime_error("Trying to convert unknown MicroProfilerName to string");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void startProfiling();
|
||
|
static void stopProfiling();
|
||
|
static bool isProfiling();
|
||
|
static void runInternalBenchmark();
|
||
|
};
|
||
|
|
||
|
class MicroProfilerSection {
|
||
|
public:
|
||
|
MicroProfilerSection(MicroProfilerName name);
|
||
|
~MicroProfilerSection();
|
||
|
|
||
|
private:
|
||
|
bool isProfiling_;
|
||
|
MicroProfilerName name_;
|
||
|
uint_fast64_t startTime_;
|
||
|
uint_fast32_t startNumProfileSections_;
|
||
|
};
|
||
|
|
||
|
} }
|