mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 01:59:58 +00:00
add jit event
Signed-off-by: zoumujia <zoumujia0920@163.com>
This commit is contained in:
parent
8c2e576664
commit
18e474aedc
1
BUILD.gn
1
BUILD.gn
@ -682,6 +682,7 @@ ecma_source = [
|
||||
"ecmascript/interpreter/slow_runtime_stub.cpp",
|
||||
"ecmascript/intl/locale_helper.cpp",
|
||||
"ecmascript/jit/jit.cpp",
|
||||
"ecmascript/jit/jit_dfx.cpp",
|
||||
"ecmascript/jit/jit_task.cpp",
|
||||
"ecmascript/jit/jit_thread.cpp",
|
||||
"ecmascript/jit/jit_profiler.cpp",
|
||||
|
@ -609,6 +609,10 @@ void AOTFileGenerator::GetMemoryCodeInfos(MachineCodeDesc &machineCodeDesc)
|
||||
LOG_COMPILER(WARN) << "error: code size of generated an file is empty!";
|
||||
return;
|
||||
}
|
||||
|
||||
if (log_->OutputASM()) {
|
||||
PrintMergedCodeComment();
|
||||
}
|
||||
GenerateMergedStackmapSection();
|
||||
|
||||
// get func entry Map
|
||||
|
@ -544,6 +544,9 @@ void Deoptimizier::UpdateAndDumpDeoptInfo(kungfu::DeoptType type)
|
||||
method->SetDeoptThreshold(--deoptThreshold);
|
||||
} else {
|
||||
method->ClearAOTStatusWhenDeopt();
|
||||
if (func->GetMachineCode().IsMachineCodeObject()) {
|
||||
Jit::GetInstance()->GetJitDfx()->SetJitDeoptCount();
|
||||
}
|
||||
func->SetCodeEntry(reinterpret_cast<uintptr_t>(nullptr));
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,13 @@ void Jit::SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnableFastJ
|
||||
isApp_ = options.IsEnableAPPJIT();
|
||||
initJitCompiler_(options);
|
||||
JitTaskpool::GetCurrentTaskpool()->Initialize();
|
||||
|
||||
jitDfx_ = JitDfx::GetInstance();
|
||||
if (options.IsEnableJitDfxDump()) {
|
||||
jitDfx_->EnableDump();
|
||||
}
|
||||
jitDfx_->ResetCompilerTime();
|
||||
jitDfx_->ResetBlockUIEventTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -236,11 +243,14 @@ void Jit::Compile(EcmaVM *vm, JSHandle<JSFunction> &jsFunction, CompilerTier tie
|
||||
return;
|
||||
}
|
||||
|
||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "JIT::Compile");
|
||||
Method *method = Method::Cast(jsFunction->GetMethod().GetTaggedObject());
|
||||
CString fileDesc = method->GetJSPandaFile()->GetJSPandaFileDesc();
|
||||
CString methodName = fileDesc + ":" + method->GetRecordNameStr() + "." + CString(method->GetMethodName());
|
||||
uint32_t codeSize = method->GetCodeSize();
|
||||
CString methodInfo = methodName + ", code size:" + ToCString(codeSize);
|
||||
jit->GetJitDfx()->SetBundleName(vm->GetBundleName());
|
||||
jit->GetJitDfx()->SetPidNumber(vm->GetJSThread()->GetThreadId());
|
||||
CString methodInfo = methodName + ", bytecode size:" + ToCString(codeSize);
|
||||
constexpr uint32_t maxSize = 9000;
|
||||
if (codeSize > maxSize) {
|
||||
if (tier == CompilerTier::BASELINE) {
|
||||
@ -251,6 +261,9 @@ void Jit::Compile(EcmaVM *vm, JSHandle<JSFunction> &jsFunction, CompilerTier tie
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CString msg = "compile method:" + methodInfo + ", in work thread";
|
||||
TimeScope scope(msg, tier);
|
||||
if (vm->GetJSThread()->IsMachineCodeLowMemory()) {
|
||||
if (tier == CompilerTier::BASELINE) {
|
||||
LOG_BASELINEJIT(DEBUG) << "skip jit task, as low code memory:" << methodInfo;
|
||||
@ -281,18 +294,18 @@ void Jit::Compile(EcmaVM *vm, JSHandle<JSFunction> &jsFunction, CompilerTier tie
|
||||
// using hole value to indecate compiling. todo: reset when failed
|
||||
if (tier == CompilerTier::FAST) {
|
||||
jsFunction->SetMachineCode(vm->GetJSThread(), JSTaggedValue::Hole());
|
||||
jit->GetJitDfx()->SetTriggerCount(false);
|
||||
} else {
|
||||
ASSERT(tier == CompilerTier::BASELINE);
|
||||
jsFunction->SetBaselineCode(vm->GetJSThread(), JSTaggedValue::Hole());
|
||||
jit->GetJitDfx()->SetTriggerCount(true);
|
||||
}
|
||||
|
||||
{
|
||||
CString msg = "compile method:" + methodInfo + ", in work thread";
|
||||
TimeScope scope(msg, tier);
|
||||
JitTaskpool::GetCurrentTaskpool()->WaitForJitTaskPoolReady();
|
||||
EcmaVM *compilerVm = JitTaskpool::GetCurrentTaskpool()->GetCompilerVm();
|
||||
std::shared_ptr<JitTask> jitTask = std::make_shared<JitTask>(vm->GetJSThread(), compilerVm->GetJSThread(),
|
||||
jit, jsFunction, tier, methodName, offset, vm->GetJSThread()->GetThreadId(), mode);
|
||||
jit, jsFunction, tier, methodName, offset, vm->GetJSThread()->GetThreadId(), mode, jit->GetJitDfx());
|
||||
|
||||
jitTask->PrepareCompile();
|
||||
JitTaskpool::GetCurrentTaskpool()->PostTask(
|
||||
@ -303,6 +316,10 @@ void Jit::Compile(EcmaVM *vm, JSHandle<JSFunction> &jsFunction, CompilerTier tie
|
||||
jitTask->WaitFinish();
|
||||
jitTask->InstallCode();
|
||||
}
|
||||
int spendTime = scope.TotalSpentTimeInMicroseconds();
|
||||
jitTask->SetMainThreadCompilerTime(spendTime);
|
||||
jit->GetJitDfx()->SetTotalTimeOnMainThread(spendTime);
|
||||
jit->GetJitDfx()->PrintJitStatsLog();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "ecmascript/mem/machine_code.h"
|
||||
#include "ecmascript/compiler/compiler_log.h"
|
||||
#include "ecmascript/jit/jit_thread.h"
|
||||
#include "ecmascript/jit/jit_dfx.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
class JitTask;
|
||||
@ -87,6 +88,11 @@ public:
|
||||
{
|
||||
return isProfileNeedDump_;
|
||||
}
|
||||
|
||||
JitDfx *GetJitDfx() const
|
||||
{
|
||||
return jitDfx_;
|
||||
}
|
||||
NO_COPY_SEMANTIC(Jit);
|
||||
NO_MOVE_SEMANTIC(Jit);
|
||||
|
||||
@ -156,7 +162,10 @@ public:
|
||||
{
|
||||
ASSERT(!thread->IsJitThread());
|
||||
if (Jit::GetInstance()->IsEnableFastJit() || Jit::GetInstance()->IsEnableBaselineJit()) {
|
||||
Clock::time_point start = Clock::now();
|
||||
thread_->GetJitLock()->Lock();
|
||||
Jit::GetInstance()->GetJitDfx()->SetLockHoldingTime(
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(Clock::now() - start).count());
|
||||
locked_ = true;
|
||||
}
|
||||
}
|
||||
@ -188,6 +197,8 @@ private:
|
||||
std::unordered_map<uint32_t, std::deque<std::shared_ptr<JitTask>>> installJitTasks_;
|
||||
Mutex installJitTasksDequeMtx_;
|
||||
Mutex setEnableLock_;
|
||||
|
||||
JitDfx *jitDfx_ { nullptr };
|
||||
static constexpr int MIN_CODE_SPACE_SIZE = 1_KB;
|
||||
|
||||
static void (*initJitCompiler_)(JSRuntimeOptions);
|
||||
|
229
ecmascript/jit/jit_dfx.cpp
Normal file
229
ecmascript/jit/jit_dfx.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* 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 "ecmascript/jit/jit_dfx.h"
|
||||
#include "ecmascript/runtime.h"
|
||||
#include "libpandafile/file.h"
|
||||
#include "libpandafile/code_data_accessor.h"
|
||||
#include "libpandafile/class_data_accessor-inl.h"
|
||||
|
||||
#ifdef ENABLE_HISYSEVENT
|
||||
#include "hisysevent.h"
|
||||
#endif
|
||||
|
||||
namespace panda::ecmascript {
|
||||
JitDfx JitDfx::instance;
|
||||
thread_local uint32_t JitDfx::prefixOffset_ = 0;
|
||||
class NullStream : public std::ostream {
|
||||
public:
|
||||
NullStream() : std::ostream(&buffer_) {}
|
||||
|
||||
private:
|
||||
class NullBuffer : public std::streambuf {
|
||||
public:
|
||||
int overflow(int c) override
|
||||
{
|
||||
return c;
|
||||
}
|
||||
};
|
||||
NullBuffer buffer_;
|
||||
};
|
||||
|
||||
JitDfx *JitDfx::GetInstance()
|
||||
{
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void JitDfx::EnableDump()
|
||||
{
|
||||
isEnableDump_ = true;
|
||||
}
|
||||
|
||||
void JitDfx::OpenLogFile(uint32_t threadId)
|
||||
{
|
||||
#ifdef PANDA_TARGET_OHOS
|
||||
CString path = CString("/data/storage/ark-profile/jit_dfx_") + ToCString(threadId) + CString(".log");
|
||||
#else
|
||||
CString path = CString("jit_dfx_") + ToCString(threadId) + CString(".log");
|
||||
#endif
|
||||
logFiles_[threadId].open(path.c_str(), std::ios::out);
|
||||
}
|
||||
|
||||
std::ostream &JitDfx::GetLogFileStream()
|
||||
{
|
||||
if (!isEnableDump_) {
|
||||
static NullStream nullStream_;
|
||||
return nullStream_;
|
||||
}
|
||||
uint32_t threadId = os::thread::GetCurrentThreadId();
|
||||
auto it = logFiles_.find(threadId);
|
||||
if (it == logFiles_.end()) {
|
||||
OpenLogFile(threadId);
|
||||
}
|
||||
return logFiles_[threadId];
|
||||
}
|
||||
|
||||
void JitDfx::DumpBytecodeInst(Method *method)
|
||||
{
|
||||
if (!isEnableDump_) {
|
||||
return;
|
||||
}
|
||||
CString methodInfo = method->GetRecordNameStr() + "." + CString(method->GetMethodName());
|
||||
MethodLiteral *methodLiteral = method->GetMethodLiteral();
|
||||
auto jsPandaFile = method->GetJSPandaFile();
|
||||
const panda_file::File *pf = jsPandaFile->GetPandaFile();
|
||||
panda_file::File::EntityId methodIdx = methodLiteral->GetMethodId();
|
||||
panda_file::MethodDataAccessor mda(*pf, methodIdx);
|
||||
auto codeId = mda.GetCodeId();
|
||||
panda_file::CodeDataAccessor codeDataAccessor(*pf, codeId.value());
|
||||
uint32_t codeSize = codeDataAccessor.GetCodeSize();
|
||||
const uint8_t *insns = codeDataAccessor.GetInstructions();
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "BytecodeInst func:" << methodInfo << "\n";
|
||||
auto bcIns = BytecodeInst(insns);
|
||||
auto bcInsLast = bcIns.JumpTo(codeSize);
|
||||
while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
|
||||
ss << bcIns << std::endl;
|
||||
auto nextInst = bcIns.GetNext();
|
||||
bcIns = nextInst;
|
||||
}
|
||||
|
||||
GetLogFileStream() << ss.str() << std::endl;
|
||||
}
|
||||
|
||||
void JitDfx::TraceJitCode(Method *method, bool isEntry)
|
||||
{
|
||||
if (!isEnableDump_) {
|
||||
return;
|
||||
}
|
||||
if (!isEntry) {
|
||||
prefixOffset_ -= 1;
|
||||
}
|
||||
CString prefixStr = isEntry ? CString("JitCodeEntry:") : CString("JitCodeExit :");
|
||||
CString methodInfo = method->GetRecordNameStr() + "." + CString(method->GetMethodName());
|
||||
static CString blackSpace(" ");
|
||||
CString prefix;
|
||||
for (uint32_t i = 0; i < prefixOffset_; i++) {
|
||||
prefix += blackSpace;
|
||||
}
|
||||
if (isEntry) {
|
||||
prefixOffset_ += 1;
|
||||
}
|
||||
LOG_JIT(INFO) << prefixStr << prefix << methodInfo;
|
||||
}
|
||||
|
||||
void JitDfx::PrintJitStatsLog()
|
||||
{
|
||||
if (checkUploadConditions()) {
|
||||
LOG_JIT(DEBUG) << "Jit Compiler stats Log: "
|
||||
<< " bundleName: " << GetBundleName()
|
||||
<< " pid: " << GetPidNumber()
|
||||
<< " total main thread time: " << GetTotalTimeOnMainThread()
|
||||
<< " total Jit thread time: " << GetTotalTimeOnJitThread()
|
||||
<< " total Baseline Jit times: " << GetTotalBaselineJitCount()
|
||||
<< " total Fastopt Jit times: " << GetTotalFastoptJitCount()
|
||||
<< " report time interval:"
|
||||
<< std::chrono::duration_cast<std::chrono::seconds>(Clock::now() - jitEventParams.start_).count()
|
||||
<< " total time on hold lock: " << GetTotalLockHoldingTime()
|
||||
<< " max time on hold lock: " << GetMaxLockHoldingTime()
|
||||
<< " longtime of hold lock: " << GetLongtimeLockCount()
|
||||
<< " JitDeopt times: " << GetJitDeoptCount()
|
||||
<< "\n";
|
||||
SendJitStatsEvent();
|
||||
InitializeRecord();
|
||||
}
|
||||
}
|
||||
|
||||
void JitDfx::SendJitStatsEvent() const
|
||||
{
|
||||
#ifdef ENABLE_HISYSEVENT
|
||||
int32_t ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::ARKTS_RUNTIME,
|
||||
"ARK_STATS_JIT",
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
|
||||
"BUNDLE_NAME", ConvertToStdString(GetBundleName()),
|
||||
"PID", GetPidNumber(),
|
||||
"TIME_INTERVAL",
|
||||
std::chrono::duration_cast<std::chrono::seconds>(Clock::now() - jitEventParams.start_).count(),
|
||||
"TOTAL_BASELINE_JIT_TIMES", GetTotalBaselineJitCount(),
|
||||
"TOTAL_FASTOPT_JIT_TIMES", GetTotalFastoptJitCount(),
|
||||
"TOTAL_TIME_ON_MAIN_THREAD", GetTotalTimeOnMainThread(),
|
||||
"TOTAL_TIME_ON_JIT_THREAD", GetTotalTimeOnJitThread(),
|
||||
"TOTAL_TIME_ON_HOLD_LOCK", GetTotalLockHoldingTime(),
|
||||
"MAX_TIME_ON_HOLD_LOCK", GetMaxLockHoldingTime(),
|
||||
"LONG_TIME_OF_HOLD_LOCK", GetLongtimeLockCount(),
|
||||
"UNINSTALL_TIME", GetJitDeoptCount());
|
||||
if (ret != 0) {
|
||||
LOG_JIT(ERROR) << "Jit Compiler Stats send stats event failed! ret = " << ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void JitDfx::PrintJitBlockUILog()
|
||||
{
|
||||
std::string jitType = isBaselineJit_ ? "Baseline JIT" : "Fast optimization JIT";
|
||||
LOG_JIT(DEBUG) << "Jit BlockUI Event Log: "
|
||||
<< " bundleName: " << GetBundleName()
|
||||
<< " pid: " << GetPidNumber()
|
||||
<< " Single main thread time: " << GetSingleTimeOnMainThread()
|
||||
<< " Single Jit thread time: " << GetSingleTimeOnJitThread()
|
||||
<< " Jit type: " << jitType
|
||||
<< " method info: " << GetMethodInfo()
|
||||
<< "\n";
|
||||
SendJitBlockUIEvent();
|
||||
InitializeBlockUIRecord();
|
||||
}
|
||||
|
||||
void JitDfx::SendJitBlockUIEvent() const
|
||||
{
|
||||
#ifdef ENABLE_HISYSEVENT
|
||||
std::string jitType = isBaselineJit_ ? "Baseline JIT" : "Fast optimization JIT";
|
||||
int32_t ret = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::ARKTS_RUNTIME,
|
||||
"ARK_BLOCKUI_JIT",
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
|
||||
"BUNDLE_NAME", ConvertToStdString(GetBundleName()),
|
||||
"PID", GetPidNumber(),
|
||||
"JIT_TYPE", jitType,
|
||||
"JIT_FUNCTION_NAME", ConvertToStdString(GetMethodInfo()),
|
||||
"TIME_ON_MAIN_THREAD", GetSingleTimeOnMainThread(),
|
||||
"TIME_ON_JIT_THREAD", GetSingleTimeOnJitThread());
|
||||
if (ret != 0) {
|
||||
LOG_JIT(ERROR) << "Jit Compiler Stats send jit blockUI event failed! ret = " << ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void JitDfx::InitializeRecord()
|
||||
{
|
||||
jitEventParams.totalBaselineJitTimes_.store(0);
|
||||
jitEventParams.totalFastoptJitTimes_.store(0);
|
||||
jitEventParams.jitDeoptTimes_.store(0);
|
||||
jitEventParams.longtimeLockTimes_.store(0);
|
||||
jitEventParams.totalTimeOnMainThread_.store(0);
|
||||
jitEventParams.totalTimeOnJitThread_.store(0);
|
||||
jitEventParams.totalLockHoldingTime_.store(0);
|
||||
jitEventParams.maxLockHoldingTime_ .store(0);
|
||||
ResetCompilerTime();
|
||||
}
|
||||
|
||||
void JitDfx::InitializeBlockUIRecord()
|
||||
{
|
||||
jitEventParams.singleTimeOnMainThread_.store(0);
|
||||
jitEventParams.singleTimeOnJitThread_.store(0);
|
||||
isBaselineJit_ = true;
|
||||
methodInfo_ = "";
|
||||
ResetBlockUIEventTime();
|
||||
}
|
||||
} // namespace panda::ecmascript
|
259
ecmascript/jit/jit_dfx.h
Normal file
259
ecmascript/jit/jit_dfx.h
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_JIT_JIT_DFX_H
|
||||
#define ECMASCRIPT_JIT_JIT_DFX_H
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
|
||||
#include "ecmascript/log.h"
|
||||
#include "ecmascript/mem/c_string.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
using Clock = std::chrono::high_resolution_clock;
|
||||
using Duration = std::chrono::duration<uint64_t, std::nano>;
|
||||
|
||||
struct JitEventParams {
|
||||
std::atomic<int> totalBaselineJitTimes_;
|
||||
std::atomic<int> totalFastoptJitTimes_;
|
||||
std::atomic<int> jitDeoptTimes_;
|
||||
std::atomic<int> longtimeLockTimes_;
|
||||
std::atomic<int> singleTimeOnMainThread_;
|
||||
std::atomic<int> totalTimeOnMainThread_;
|
||||
std::atomic<int> singleTimeOnJitThread_;
|
||||
std::atomic<int> totalTimeOnJitThread_;
|
||||
std::atomic<int> totalLockHoldingTime_;
|
||||
std::atomic<int> maxLockHoldingTime_;
|
||||
Clock::time_point start_;
|
||||
Clock::time_point blockUIEventstart_;
|
||||
|
||||
JitEventParams() : totalBaselineJitTimes_(0), totalFastoptJitTimes_(0), jitDeoptTimes_(0),
|
||||
longtimeLockTimes_(0), singleTimeOnMainThread_(0), totalTimeOnMainThread_(0),
|
||||
singleTimeOnJitThread_(0), totalTimeOnJitThread_(0), totalLockHoldingTime_(0),
|
||||
maxLockHoldingTime_(0), start_(Clock::now()), blockUIEventstart_(Clock::now()) {}
|
||||
};
|
||||
|
||||
class Method;
|
||||
class JitDfx {
|
||||
public:
|
||||
using ThreadId = uint32_t;
|
||||
static JitDfx *GetInstance();
|
||||
void EnableDump();
|
||||
bool IsEnableDump() const
|
||||
{
|
||||
return isEnableDump_;
|
||||
}
|
||||
|
||||
std::ostream &GetLogFileStream();
|
||||
|
||||
void DumpBytecodeInst(Method *method);
|
||||
void TraceJitCode(Method *method, bool isEntry);
|
||||
|
||||
void SetBundleName(CString bundleName)
|
||||
{
|
||||
bundleName_ = bundleName;
|
||||
}
|
||||
|
||||
CString GetBundleName() const
|
||||
{
|
||||
return bundleName_;
|
||||
}
|
||||
|
||||
void SetPidNumber(ThreadId number)
|
||||
{
|
||||
pidNum_ = number;
|
||||
}
|
||||
|
||||
ThreadId GetPidNumber() const
|
||||
{
|
||||
return pidNum_;
|
||||
}
|
||||
|
||||
void SetTotalTimeOnMainThread(int time)
|
||||
{
|
||||
jitEventParams.totalTimeOnMainThread_.fetch_add(time);
|
||||
}
|
||||
|
||||
int GetTotalTimeOnMainThread() const
|
||||
{
|
||||
return jitEventParams.totalTimeOnMainThread_.load() / CONVERT_TO_MILLISECOND;
|
||||
}
|
||||
|
||||
void SetSingleTimeOnMainThread(int time)
|
||||
{
|
||||
jitEventParams.singleTimeOnMainThread_.store(time);
|
||||
}
|
||||
|
||||
int GetSingleTimeOnMainThread() const
|
||||
{
|
||||
return jitEventParams.singleTimeOnMainThread_.load() / CONVERT_TO_MILLISECOND;
|
||||
}
|
||||
|
||||
void SetTotalTimeOnJitThread(int time)
|
||||
{
|
||||
jitEventParams.totalTimeOnJitThread_.fetch_add(time);
|
||||
}
|
||||
|
||||
int GetTotalTimeOnJitThread() const
|
||||
{
|
||||
return jitEventParams.totalTimeOnJitThread_.load() / CONVERT_TO_MILLISECOND;
|
||||
}
|
||||
|
||||
void SetSingleTimeOnJitThread(int time)
|
||||
{
|
||||
jitEventParams.singleTimeOnJitThread_.store(time);
|
||||
}
|
||||
|
||||
int GetSingleTimeOnJitThread() const
|
||||
{
|
||||
return jitEventParams.singleTimeOnJitThread_.load() / CONVERT_TO_MILLISECOND;
|
||||
}
|
||||
|
||||
void SetTriggerCount(bool isBaselineJit)
|
||||
{
|
||||
if (isBaselineJit) {
|
||||
jitEventParams.totalBaselineJitTimes_.fetch_add(1);
|
||||
} else {
|
||||
jitEventParams.totalFastoptJitTimes_.fetch_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
int GetTotalBaselineJitCount() const
|
||||
{
|
||||
return jitEventParams.totalBaselineJitTimes_.load();
|
||||
}
|
||||
|
||||
int GetTotalFastoptJitCount() const
|
||||
{
|
||||
return jitEventParams.totalFastoptJitTimes_.load();
|
||||
}
|
||||
|
||||
void SetIsBaselineJit(bool isBaselineJit)
|
||||
{
|
||||
isBaselineJit_ = isBaselineJit;
|
||||
}
|
||||
|
||||
bool GetIsBaselineJit() const
|
||||
{
|
||||
return isBaselineJit_;
|
||||
}
|
||||
|
||||
void SetMethodInfo(CString method)
|
||||
{
|
||||
methodInfo_ = method;
|
||||
}
|
||||
|
||||
CString GetMethodInfo() const
|
||||
{
|
||||
return methodInfo_;
|
||||
}
|
||||
|
||||
void SetLockHoldingTime(int time)
|
||||
{
|
||||
jitEventParams.totalLockHoldingTime_.fetch_add(time);
|
||||
if (time > jitEventParams.maxLockHoldingTime_.load()) {
|
||||
jitEventParams.maxLockHoldingTime_.store(time);
|
||||
}
|
||||
if (time > HOLD_LOCK_LIMIT) {
|
||||
jitEventParams.longtimeLockTimes_.fetch_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
int GetTotalLockHoldingTime() const
|
||||
{
|
||||
return jitEventParams.totalLockHoldingTime_.load() / CONVERT_TO_MILLISECOND;
|
||||
}
|
||||
|
||||
int GetMaxLockHoldingTime() const
|
||||
{
|
||||
return jitEventParams.maxLockHoldingTime_.load() / CONVERT_TO_MILLISECOND;
|
||||
}
|
||||
|
||||
int GetLongtimeLockCount() const
|
||||
{
|
||||
return jitEventParams.longtimeLockTimes_.load();
|
||||
}
|
||||
|
||||
void SetJitDeoptCount()
|
||||
{
|
||||
jitEventParams.jitDeoptTimes_.fetch_add(1);
|
||||
}
|
||||
|
||||
int GetJitDeoptCount() const
|
||||
{
|
||||
return jitEventParams.jitDeoptTimes_.load();
|
||||
}
|
||||
|
||||
void ResetCompilerTime()
|
||||
{
|
||||
jitEventParams.start_ = Clock::now();
|
||||
}
|
||||
|
||||
void ResetBlockUIEventTime()
|
||||
{
|
||||
jitEventParams.blockUIEventstart_ = Clock::now();
|
||||
}
|
||||
|
||||
bool ReportBlockUIEvent(int time)
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(Clock::now() -
|
||||
jitEventParams.blockUIEventstart_).count() >= MIN_SEND_INTERVAL && (time >= MAX_OCCUPY_MAIN_THREAD_TIME);
|
||||
}
|
||||
|
||||
void SetBlockUIEventInfo(CString info, bool isBaselineJit, int mainThreadTime, int jitThreadTime)
|
||||
{
|
||||
SetMethodInfo(info);
|
||||
SetIsBaselineJit(isBaselineJit);
|
||||
SetSingleTimeOnMainThread(mainThreadTime);
|
||||
SetSingleTimeOnJitThread(jitThreadTime);
|
||||
PrintJitBlockUILog();
|
||||
}
|
||||
|
||||
void PrintJitStatsLog();
|
||||
void PrintJitBlockUILog();
|
||||
|
||||
private:
|
||||
void OpenLogFile(uint32_t threadId);
|
||||
void InitializeRecord();
|
||||
void InitializeBlockUIRecord();
|
||||
void SendJitStatsEvent() const;
|
||||
void SendJitBlockUIEvent() const;
|
||||
bool checkUploadConditions() const
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(Clock::now() - jitEventParams.start_).count() >=
|
||||
MIN_SEND_INTERVAL && (jitEventParams.totalBaselineJitTimes_.load() +
|
||||
jitEventParams.totalFastoptJitTimes_.load()) >= MAX_TRIGGER_TIMES;
|
||||
}
|
||||
|
||||
static JitDfx instance;
|
||||
bool isEnableDump_ {false};
|
||||
bool isBaselineJit_ {true};
|
||||
std::map<uint32_t, std::ofstream> logFiles_;
|
||||
static thread_local uint32_t prefixOffset_;
|
||||
|
||||
CString bundleName_ = "";
|
||||
CString methodInfo_ = "";
|
||||
ThreadId pidNum_ {0};
|
||||
JitEventParams jitEventParams;
|
||||
static constexpr int MAX_TRIGGER_TIMES = 100;
|
||||
static constexpr int MIN_SEND_INTERVAL = 60; // seconds
|
||||
static constexpr int HOLD_LOCK_LIMIT = 1000; // microseconds
|
||||
static constexpr int MAX_OCCUPY_MAIN_THREAD_TIME = 3000; // microseconds
|
||||
static constexpr int CONVERT_TO_MILLISECOND = 1000;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_JIT_JIT_DFX_H
|
@ -37,7 +37,8 @@ uint32_t JitTaskpool::TheMostSuitableThreadNum([[maybe_unused]]uint32_t threadNu
|
||||
}
|
||||
|
||||
JitTask::JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, JSHandle<JSFunction> &jsFunction,
|
||||
CompilerTier tier, CString &methodName, int32_t offset, uint32_t taskThreadId, JitCompileMode mode)
|
||||
CompilerTier tier, CString &methodName, int32_t offset, uint32_t taskThreadId,
|
||||
JitCompileMode mode, JitDfx *JitDfx)
|
||||
: hostThread_(hostThread),
|
||||
compilerThread_(compilerThread),
|
||||
jit_(jit),
|
||||
@ -50,6 +51,7 @@ JitTask::JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit, JSHan
|
||||
taskThreadId_(taskThreadId),
|
||||
ecmaContext_(nullptr),
|
||||
jitCompileMode_(mode),
|
||||
jitDfx_(JitDfx),
|
||||
runState_(RunState::INIT)
|
||||
{
|
||||
ecmaContext_ = hostThread->GetCurrentEcmaContext();
|
||||
@ -73,6 +75,7 @@ void JitTask::PrepareCompile()
|
||||
|
||||
void JitTask::Optimize()
|
||||
{
|
||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "JIT::Compiler frontend");
|
||||
bool res = jit_->JitCompile(compilerTask_, this);
|
||||
if (!res) {
|
||||
SetCompileFailed();
|
||||
@ -85,6 +88,7 @@ void JitTask::Finalize()
|
||||
return;
|
||||
}
|
||||
|
||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "JIT::Compiler backend");
|
||||
bool res = jit_->JitFinalize(compilerTask_, this);
|
||||
if (!res) {
|
||||
SetCompileFailed();
|
||||
@ -200,7 +204,9 @@ void JitTask::InstallCode()
|
||||
methodHandle->GetMethodId(),
|
||||
std::make_pair(methodHandle.GetTaggedType(), machineCodeObj.GetTaggedType()));
|
||||
}
|
||||
LOG_JIT(DEBUG) <<"Install fast jit machine code:" << GetMethodName();
|
||||
uintptr_t codeAddrEnd = codeAddr + machineCodeObj->GetInstructionsSize();
|
||||
LOG_JIT(DEBUG) <<"Install fast jit machine code:" << GetMethodName() << ", code range:" <<
|
||||
reinterpret_cast<void*>(codeAddr) <<"--" << reinterpret_cast<void*>(codeAddrEnd);
|
||||
#if ECMASCRIPT_ENABLE_JIT_WARMUP_PROFILER
|
||||
auto &profMap = JitWarmupProfiler::GetInstance()->profMap_;
|
||||
if (profMap.find(GetMethodName()) != profMap.end()) {
|
||||
@ -276,6 +282,7 @@ bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
|
||||
}
|
||||
DISALLOW_HEAP_ACCESS;
|
||||
|
||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "JIT::Compile");
|
||||
// JitCompileMode ASYNC
|
||||
// check init ok
|
||||
jitTask_->SetRunState(RunState::RUNNING);
|
||||
@ -299,6 +306,15 @@ bool JitTask::AsyncTask::Run([[maybe_unused]] uint32_t threadIndex)
|
||||
// info main thread compile complete
|
||||
jitTask_->jit_->RequestInstallCode(jitTask_);
|
||||
}
|
||||
int compilerTime = scope.TotalSpentTimeInMicroseconds();
|
||||
jitTask_->jitDfx_->SetTotalTimeOnJitThread(compilerTime);
|
||||
if (jitTask_->jitDfx_->ReportBlockUIEvent(jitTask_->mainThreadCompileTime_)) {
|
||||
jitTask_->jitDfx_->SetBlockUIEventInfo(
|
||||
jitTask_->methodName_,
|
||||
jitTask_->compilerTier_ == CompilerTier::BASELINE ? true : false,
|
||||
jitTask_->mainThreadCompileTime_, compilerTime);
|
||||
}
|
||||
jitTask_->jitDfx_->PrintJitStatsLog();
|
||||
}
|
||||
jitvm->ReSetHostVM();
|
||||
jitTask_->SetRunStateFinish();
|
||||
|
@ -91,7 +91,7 @@ class JitTask {
|
||||
public:
|
||||
JitTask(JSThread *hostThread, JSThread *compilerThread, Jit *jit,
|
||||
JSHandle<JSFunction> &jsFunction, CompilerTier tier, CString &methodName, int32_t offset,
|
||||
uint32_t taskThreadId, JitCompileMode mode);
|
||||
uint32_t taskThreadId, JitCompileMode mode, JitDfx *jitDfx);
|
||||
// for ut
|
||||
JitTask(EcmaVM *hVm, EcmaVM *cVm, Jit *jit, uint32_t taskThreadId, JitCompileMode mode);
|
||||
~JitTask();
|
||||
@ -213,6 +213,16 @@ public:
|
||||
return jitCompileMode_ == JitCompileMode::ASYNC;
|
||||
}
|
||||
|
||||
void SetMainThreadCompilerTime(int time)
|
||||
{
|
||||
mainThreadCompileTime_ = time;
|
||||
}
|
||||
|
||||
int GetMainThreadCompilerTime() const
|
||||
{
|
||||
return mainThreadCompileTime_;
|
||||
}
|
||||
|
||||
class AsyncTask : public Task {
|
||||
public:
|
||||
explicit AsyncTask(std::shared_ptr<JitTask>jitTask, int32_t id) : Task(id), jitTask_(jitTask) { }
|
||||
@ -278,6 +288,8 @@ private:
|
||||
std::unique_ptr<SustainingJSHandle> sustainingJSHandle_;
|
||||
EcmaContext *ecmaContext_;
|
||||
JitCompileMode jitCompileMode_;
|
||||
JitDfx *jitDfx_ { nullptr };
|
||||
int mainThreadCompileTime_ {0};
|
||||
|
||||
std::atomic<RunState> runState_;
|
||||
Mutex runStateMutex_;
|
||||
|
@ -1107,6 +1107,16 @@ public:
|
||||
return enableAPPJIT_;
|
||||
}
|
||||
|
||||
bool IsEnableJitDfxDump() const
|
||||
{
|
||||
return isEnableJitDfxDump_;
|
||||
}
|
||||
|
||||
void SetEnableJitDfxDump(bool value)
|
||||
{
|
||||
isEnableJitDfxDump_ = value;
|
||||
}
|
||||
|
||||
void SetEnableOSR(bool value)
|
||||
{
|
||||
enableOSR_ = value;
|
||||
@ -1786,6 +1796,7 @@ private:
|
||||
bool enableOptPGOType_ {true};
|
||||
bool enableFastJIT_{false};
|
||||
bool enableAPPJIT_{false};
|
||||
bool isEnableJitDfxDump_ {false};
|
||||
bool enableOSR_{false};
|
||||
uint16_t jitHotnessThreshold_ {2};
|
||||
uint16_t osrHotnessThreshold_ {2};
|
||||
|
@ -41,6 +41,11 @@ public:
|
||||
return (float) duration.count() / MILLION_TIME;
|
||||
}
|
||||
|
||||
int TotalSpentTimeInMicroseconds() const
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(Clock::now() - start_).count();
|
||||
}
|
||||
|
||||
double GetCurTime() const
|
||||
{
|
||||
auto curTime_ = Duration(start_.time_since_epoch());
|
||||
|
@ -41,3 +41,26 @@ ARK_COMPILER_LOG:
|
||||
IS_LITECG: {type: BOOL, desc: codegen type is litecg}
|
||||
COMPILER_METHOD_COUNT: {type: UINT32, desc: compiler method count}
|
||||
PGO_FILE_LEGAL: {type: BOOL, desc: pgo file is legal}
|
||||
|
||||
ARK_STATS_JIT:
|
||||
__BASE: {type: STATISTIC, level: MINOR, desc: ARKTSRUNTIME JIT COMPILER KEY STATS, preserve: true}
|
||||
BUNDLE_NAME: {type: STRING, desc: Application bundle name}
|
||||
PID: {type: INT32, desc: pid}
|
||||
TIME_INTERVAL: {type: INT32, desc: Interval for reporting the event}
|
||||
TOTAL_BASELINE_JIT_TIMES: {type: INT32, desc: Number of baseline JIT triggering times within this period}
|
||||
TOTAL_FASTOPT_JIT_TIMES: {type: INT32, desc: Number of fast optimization JIT triggering times within this period}
|
||||
TOTAL_TIME_ON_MAIN_THREAD: {type: INT32, desc: The total time occupied by JIT on the main thread within this period}
|
||||
TOTAL_TIME_ON_JIT_THREAD: {type: INT32, desc: The total time occupied on the JIT thread within this period}
|
||||
TOTAL_TIME_ON_HOLD_LOCK: {type: INT32, desc: Total lock holding time within this period}
|
||||
MAX_TIME_ON_HOLD_LOCK: {type: INT32, desc: Maximum lock holding time within this period}
|
||||
LONG_TIME_OF_HOLD_LOCK: {type: INT32, desc: Times of long-time lock holding within this period}
|
||||
UNINSTALL_TIME: {type: INT32, desc: JIT deoptimizer times within this period}
|
||||
|
||||
ARK_BLOCKUI_JIT:
|
||||
__BASE: {type: STATISTIC, level: MINOR, desc: ARKTSRUNTIME JIT COMPILER BLOCKUI EVENT, preserve: true}
|
||||
BUNDLE_NAME: {type: STRING, desc: Application bundle name}
|
||||
PID: {type: INT32, desc: pid}
|
||||
JIT_TYPE: {type: STRING, desc: Triggered jit type}
|
||||
JIT_FUNCTION_NAME: {type: STRING, desc: JIT compiled function name}
|
||||
TIME_ON_MAIN_THREAD: {type: INT32, desc: The time occupied by JIT on the main thread}
|
||||
TIME_ON_JIT_THREAD: {type: INT32, desc: The time occupied on JIT thread}
|
Loading…
Reference in New Issue
Block a user