cpp/profiler/jni.cpp (181 lines of code) (raw):
/**
* Copyright 2004-present, Facebook, Inc.
*
* 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 <fb/xplat_init.h>
#include <fbjni/fbjni.h>
#include <jni.h>
#include <profilo/jni/JMultiBufferLogger.h>
#include <profilo/profiler/ArtCompatibility.h>
#include <profilo/profiler/BaseTracer.h>
#include <profilo/util/common.h>
#include <profilo/profiler/ArtUnwindcTracer_500.h>
#include <profilo/profiler/ArtUnwindcTracer_510.h>
#include <profilo/profiler/ArtUnwindcTracer_600.h>
#include <profilo/profiler/ArtUnwindcTracer_700.h>
#include <profilo/profiler/ArtUnwindcTracer_710.h>
#include <profilo/profiler/ArtUnwindcTracer_711.h>
#include <profilo/profiler/ArtUnwindcTracer_712.h>
#include <profilo/profiler/ArtUnwindcTracer_800.h>
#include <profilo/profiler/ArtUnwindcTracer_810.h>
#include <profilo/profiler/ArtUnwindcTracer_900.h>
#include <profilo/profiler/DalvikTracer.h>
#include <profilo/profiler/ExternalTracerManager.h>
#include <profilo/profiler/JSTracer.h>
#if HAS_NATIVE_TRACER
#include <profilo/profiler/NativeTracer.h>
#endif
#include "SamplingProfiler.h"
using namespace facebook::profilo;
using namespace facebook::profilo::profiler;
using facebook::profilo::logger::JMultiBufferLogger;
const char* CPUProfilerType =
"com/facebook/profilo/provider/stacktrace/CPUProfiler";
const char* StackFrameThreadType =
"com/facebook/profilo/provider/stacktrace/StackFrameThread";
const char* StackTraceWhitelist =
"com/facebook/profilo/provider/stacktrace/StackTraceWhitelist";
namespace {
int32_t getCpuClockResolutionMicros(facebook::jni::alias_ref<jobject>) {
return cpuClockResolutionMicros();
}
std::unordered_map<int32_t, std::shared_ptr<BaseTracer>> makeAvailableTracers(
MultiBufferLogger& logger,
uint32_t available_tracers,
bool native_tracer_unwind_dex_frames,
int32_t native_tracer_unwind_thread_pri,
size_t native_tracer_unwind_queue_size,
bool native_tracer_log_partial_stacks) {
std::unordered_map<int32_t, std::shared_ptr<BaseTracer>> tracers;
if (available_tracers & tracers::DALVIK) {
tracers[tracers::DALVIK] = std::make_shared<DalvikTracer>();
}
#if HAS_NATIVE_TRACER
if (available_tracers & tracers::NATIVE) {
tracers[tracers::NATIVE] = std::make_shared<NativeTracer>(
logger,
native_tracer_unwind_dex_frames,
native_tracer_unwind_thread_pri,
native_tracer_unwind_queue_size,
native_tracer_log_partial_stacks);
}
#endif
if (available_tracers & tracers::ART_UNWINDC_5_0) {
tracers[tracers::ART_UNWINDC_5_0] = std::make_shared<ArtUnwindcTracer50>();
}
if (available_tracers & tracers::ART_UNWINDC_5_1) {
tracers[tracers::ART_UNWINDC_5_1] = std::make_shared<ArtUnwindcTracer51>();
}
if (available_tracers & tracers::ART_UNWINDC_6_0) {
tracers[tracers::ART_UNWINDC_6_0] = std::make_shared<ArtUnwindcTracer60>();
}
if (available_tracers & tracers::ART_UNWINDC_7_0_0) {
tracers[tracers::ART_UNWINDC_7_0_0] =
std::make_shared<ArtUnwindcTracer700>();
}
if (available_tracers & tracers::ART_UNWINDC_7_1_0) {
tracers[tracers::ART_UNWINDC_7_1_0] =
std::make_shared<ArtUnwindcTracer710>();
}
if (available_tracers & tracers::ART_UNWINDC_7_1_1) {
tracers[tracers::ART_UNWINDC_7_1_1] =
std::make_shared<ArtUnwindcTracer711>();
}
if (available_tracers & tracers::ART_UNWINDC_7_1_2) {
tracers[tracers::ART_UNWINDC_7_1_2] =
std::make_shared<ArtUnwindcTracer712>();
}
if (available_tracers & tracers::ART_UNWINDC_8_0_0) {
tracers[tracers::ART_UNWINDC_8_0_0] =
std::make_shared<ArtUnwindcTracer800>();
}
if (available_tracers & tracers::ART_UNWINDC_8_1_0) {
tracers[tracers::ART_UNWINDC_8_1_0] =
std::make_shared<ArtUnwindcTracer810>();
}
if (available_tracers & tracers::ART_UNWINDC_9_0_0) {
tracers[tracers::ART_UNWINDC_9_0_0] =
std::make_shared<ArtUnwindcTracer900>();
}
if (available_tracers & tracers::JAVASCRIPT) {
auto jsTracer = std::make_shared<JSTracer>();
tracers[tracers::JAVASCRIPT] = jsTracer;
ExternalTracerManager::getInstance().registerExternalTracer(jsTracer);
}
return tracers;
}
static jboolean nativeInitialize(
fbjni::alias_ref<jobject>,
JMultiBufferLogger* jlogger,
jint tracers,
jboolean native_tracer_unwind_dex_frames,
jint native_tracer_unwind_thread_pri,
jint native_tracer_unwind_queue_size,
jboolean native_tracer_log_partial_stacks) {
auto available_tracers = static_cast<uint32_t>(tracers);
auto& logger = jlogger->nativeInstance();
return SamplingProfiler::getInstance().initialize(
logger,
available_tracers,
makeAvailableTracers(
logger,
available_tracers,
native_tracer_unwind_dex_frames,
native_tracer_unwind_thread_pri,
static_cast<size_t>(native_tracer_unwind_queue_size),
native_tracer_log_partial_stacks));
}
static void nativeLoggerLoop(fbjni::alias_ref<jobject>) {
return SamplingProfiler::getInstance().loggerLoop();
}
static void nativeStopProfiling(fbjni::alias_ref<jobject>) {
return SamplingProfiler::getInstance().stopProfiling();
}
static jboolean nativeStartProfiling(
fbjni::alias_ref<jobject>,
jint requested_tracers,
jint sampling_rate_ms,
jint thread_detect_interval_ms,
jboolean cpu_clock_mode,
jboolean wall_clock_mode) {
return SamplingProfiler::getInstance().startProfiling(
requested_tracers,
sampling_rate_ms,
thread_detect_interval_ms,
cpu_clock_mode,
wall_clock_mode);
}
static void nativeResetFrameworkNamesSet(fbjni::alias_ref<jobject>) {
return SamplingProfiler::getInstance().resetFrameworkNamesSet();
}
static void nativeAddToWhitelist(fbjni::alias_ref<jobject>, jint tid) {
SamplingProfiler::getInstance().addToWhitelist(tid);
}
static void nativeRemoveFromWhitelist(fbjni::alias_ref<jobject>, jint tid) {
SamplingProfiler::getInstance().removeFromWhitelist(tid);
}
} // namespace
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
return facebook::xplat::initialize(vm, [] {
fbjni::registerNatives(
CPUProfilerType,
{
makeNativeMethod("nativeInitialize", nativeInitialize),
makeNativeMethod("nativeLoggerLoop", nativeLoggerLoop),
makeNativeMethod("nativeStopProfiling", nativeStopProfiling),
makeNativeMethod("nativeStartProfiling", nativeStartProfiling),
makeNativeMethod(
"nativeResetFrameworkNamesSet", nativeResetFrameworkNamesSet),
});
fbjni::registerNatives(
StackFrameThreadType,
{
makeNativeMethod(
"nativeCpuClockResolutionMicros", getCpuClockResolutionMicros),
});
fbjni::registerNatives(
StackTraceWhitelist,
{
makeNativeMethod("nativeAddToWhitelist", nativeAddToWhitelist),
makeNativeMethod(
"nativeRemoveFromWhitelist", nativeRemoveFromWhitelist),
});
artcompat::registerNatives();
});
}