Summary:
This was introduced a while ago in D3635319 (0418353249), and was never really adopted.

Changelog: [Internal]

Reviewed By: JoshuaGross

Differential Revision: D37460402

fbshipit-source-id: 70586b23697e02208c393e556625ae534773177f
This commit is contained in:
Pieter De Baets 2022-06-28 02:51:34 -07:00 коммит произвёл Facebook GitHub Bot
Родитель cf0a0eff1b
Коммит a5a956bab8
5 изменённых файлов: 0 добавлений и 377 удалений

Просмотреть файл

@ -146,7 +146,6 @@ rn_xplat_cxx_library(
"//xplat/jsi:jsi", "//xplat/jsi:jsi",
react_native_xplat_target("callinvoker:callinvoker"), react_native_xplat_target("callinvoker:callinvoker"),
react_native_xplat_target("jsinspector:jsinspector"), react_native_xplat_target("jsinspector:jsinspector"),
react_native_xplat_target("microprofiler:microprofiler"),
react_native_xplat_target("runtimeexecutor:runtimeexecutor"), react_native_xplat_target("runtimeexecutor:runtimeexecutor"),
react_native_xplat_target("reactperflogger:reactperflogger"), react_native_xplat_target("reactperflogger:reactperflogger"),
react_native_xplat_target("logger:logger"), react_native_xplat_target("logger:logger"),

Просмотреть файл

@ -1,5 +0,0 @@
---
Checks: '>
clang-diagnostic-*,
'
...

Просмотреть файл

@ -1,30 +0,0 @@
load("//tools/build_defs/oss:rn_defs.bzl", "GLOG_DEP", "cxx_library")
cxx_library(
name = "microprofiler",
srcs = [
"MicroProfiler.cpp",
],
header_namespace = "microprofiler",
exported_headers = [
"MicroProfiler.h",
],
compiler_flags = [
"-Wall",
"-Werror",
"-std=c++17",
"-fexceptions",
"-fno-data-sections",
],
force_static = True,
labels = [
"pfh:ReactNative_CommonInfrastructurePlaceholder",
"supermodule:xplat/default/public.react_native.infra",
],
visibility = [
"PUBLIC",
],
deps = [
GLOG_DEP,
],
)

Просмотреть файл

@ -1,252 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <time.h>
#include <algorithm>
#include <chrono>
#include <mutex>
#include <sstream>
#include <vector>
#include <glog/logging.h>
#include "MicroProfiler.h"
// iOS doesn't support 'thread_local'. If we reimplement this to use
// pthread_setspecific we can get rid of this
#if defined(__APPLE__)
#define MICRO_PROFILER_STUB_IMPLEMENTATION 1
#elif !defined(MICRO_PROFILER_STUB_IMPLEMENTATION)
#define MICRO_PROFILER_STUB_IMPLEMENTATION 0
#endif
namespace facebook {
namespace react {
#if !MICRO_PROFILER_STUB_IMPLEMENTATION
struct TraceData {
TraceData();
~TraceData();
void addTime(
MicroProfilerName name,
uint_fast64_t time,
uint_fast32_t internalClockCalls);
std::thread::id threadId_;
uint_fast64_t startTime_;
std::atomic_uint_fast64_t times_[MicroProfilerName::__LENGTH__] = {};
std::atomic_uint_fast32_t calls_[MicroProfilerName::__LENGTH__] = {};
std::atomic_uint_fast32_t
childProfileSections_[MicroProfilerName::__LENGTH__] = {};
};
struct ProfilingImpl {
std::mutex mutex_;
std::vector<TraceData *> allTraceData_;
bool isProfiling_ = false;
uint_fast64_t startTime_;
uint_fast64_t endTime_;
uint_fast64_t clockOverhead_;
uint_fast64_t profileSectionOverhead_;
};
static ProfilingImpl profiling;
thread_local TraceData myTraceData;
thread_local uint_fast32_t profileSections = 0;
static uint_fast64_t nowNs() {
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return uint_fast64_t(1000000000) * time.tv_sec + time.tv_nsec;
}
static uint_fast64_t diffNs(uint_fast64_t start, uint_fast64_t end) {
return end - start;
}
static std::string formatTimeNs(uint_fast64_t timeNs) {
std::ostringstream out;
out.precision(2);
if (timeNs < 1000) {
out << timeNs << "ns";
} else if (timeNs < 1000000) {
out << timeNs / 1000.0 << "us";
} else {
out << std::fixed << timeNs / 1000000.0 << "ms";
}
return out.str();
}
MicroProfilerSection::MicroProfilerSection(MicroProfilerName name)
: isProfiling_(profiling.isProfiling_),
name_(name),
startNumProfileSections_(profileSections) {
if (!isProfiling_) {
return;
}
profileSections++;
startTime_ = nowNs();
}
MicroProfilerSection::~MicroProfilerSection() {
if (!isProfiling_ || !profiling.isProfiling_) {
return;
}
auto endTime = nowNs();
auto endNumProfileSections = profileSections;
myTraceData.addTime(
name_,
endTime - startTime_,
endNumProfileSections - startNumProfileSections_ - 1);
}
TraceData::TraceData() : threadId_(std::this_thread::get_id()) {
std::lock_guard<std::mutex> lock(profiling.mutex_);
profiling.allTraceData_.push_back(this);
}
TraceData::~TraceData() {
std::lock_guard<std::mutex> lock(profiling.mutex_);
auto &infos = profiling.allTraceData_;
infos.erase(std::remove(infos.begin(), infos.end(), this), infos.end());
}
void TraceData::addTime(
MicroProfilerName name,
uint_fast64_t time,
uint_fast32_t childprofileSections) {
times_[name] += time;
calls_[name]++;
childProfileSections_[name] += childprofileSections;
}
static void printReport() {
LOG(ERROR) << "======= MICRO PROFILER REPORT =======";
LOG(ERROR) << "- Total Time: "
<< formatTimeNs(diffNs(profiling.startTime_, profiling.endTime_));
LOG(ERROR) << "- Clock Overhead: " << formatTimeNs(profiling.clockOverhead_);
LOG(ERROR) << "- Profiler Section Overhead: "
<< formatTimeNs(profiling.profileSectionOverhead_);
for (auto info : profiling.allTraceData_) {
LOG(ERROR) << "--- Thread ID 0x" << std::hex << info->threadId_ << " ---";
for (int i = 0; i < MicroProfilerName::__LENGTH__; i++) {
if (info->times_[i] > 0) {
auto totalTime = info->times_[i].load();
auto calls = info->calls_[i].load();
auto clockOverhead = profiling.clockOverhead_ * calls +
profiling.profileSectionOverhead_ *
info->childProfileSections_[i].load();
if (totalTime < clockOverhead) {
LOG(ERROR) << "- "
<< MicroProfiler::profilingNameToString(
static_cast<MicroProfilerName>(i))
<< ": "
<< "ERROR: Total time was " << totalTime
<< "ns but clock overhead was calculated to be "
<< clockOverhead << "ns!";
} else {
auto correctedTime = totalTime - clockOverhead;
auto timePerCall = correctedTime / calls;
LOG(ERROR) << "- "
<< MicroProfiler::profilingNameToString(
static_cast<MicroProfilerName>(i))
<< ": " << formatTimeNs(correctedTime) << " (" << calls
<< " calls, " << formatTimeNs(timePerCall) << "/call)";
}
}
}
}
}
static void clearProfiling() {
CHECK(!profiling.isProfiling_)
<< "Trying to clear profiling but profiling was already started!";
for (auto info : profiling.allTraceData_) {
for (unsigned int i = 0; i < MicroProfilerName::__LENGTH__; i++) {
info->times_[i] = 0;
info->calls_[i] = 0;
info->childProfileSections_[i] = 0;
}
}
}
static uint_fast64_t calculateClockOverhead() {
int numCalls = 1000000;
uint_fast64_t start = nowNs();
for (int i = 0; i < numCalls; i++) {
nowNs();
}
uint_fast64_t end = nowNs();
return (end - start) / numCalls;
}
static uint_fast64_t calculateProfileSectionOverhead() {
int numCalls = 1000000;
uint_fast64_t start = nowNs();
profiling.isProfiling_ = true;
for (int i = 0; i < numCalls; i++) {
MICRO_PROFILER_SECTION(static_cast<MicroProfilerName>(0));
}
uint_fast64_t end = nowNs();
profiling.isProfiling_ = false;
return (end - start) / numCalls;
}
void MicroProfiler::startProfiling() {
CHECK(!profiling.isProfiling_)
<< "Trying to start profiling but profiling was already started!";
profiling.clockOverhead_ = calculateClockOverhead();
profiling.profileSectionOverhead_ = calculateProfileSectionOverhead();
std::lock_guard<std::mutex> lock(profiling.mutex_);
clearProfiling();
profiling.startTime_ = nowNs();
profiling.isProfiling_ = true;
}
void MicroProfiler::stopProfiling() {
CHECK(profiling.isProfiling_)
<< "Trying to stop profiling but profiling hasn't been started!";
profiling.isProfiling_ = false;
profiling.endTime_ = nowNs();
std::lock_guard<std::mutex> lock(profiling.mutex_);
printReport();
clearProfiling();
}
bool MicroProfiler::isProfiling() {
return profiling.isProfiling_;
}
void MicroProfiler::runInternalBenchmark() {
MicroProfiler::startProfiling();
for (int i = 0; i < 1000000; i++) {
MICRO_PROFILER_SECTION_NAMED(outer, __INTERNAL_BENCHMARK_OUTER);
{ MICRO_PROFILER_SECTION_NAMED(inner, __INTERNAL_BENCHMARK_INNER); }
}
MicroProfiler::stopProfiling();
}
#else
void MicroProfiler::startProfiling() {
CHECK(false)
<< "This platform has a stub implementation of the micro profiler and cannot collect traces";
}
void MicroProfiler::stopProfiling() {}
bool MicroProfiler::isProfiling() {
return false;
}
void MicroProfiler::runInternalBenchmark() {}
#endif
} // namespace react
} // namespace facebook

Просмотреть файл

@ -1,89 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#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_;
};
} // namespace react
} // namespace facebook