Profiler supports Serialization/Deserialization timeout check

Support timeout check during the Serialization/Deserialization phase on main thread

Issue: #I9JQ0N

Signed-off-by: huangtianzhi <huangtianzhi1@huawei.com>
This commit is contained in:
huangtianzhi 2024-04-25 20:53:17 +08:00
parent eda9cbb3db
commit ad611b8525
5 changed files with 96 additions and 0 deletions

View File

@ -209,6 +209,31 @@ public:
{
return isObjHashDisplayEnabled_;
}
void EnableSerializationTimeoutCheck()
{
isSerializationTimeoutCheckEnabled_ = true;
}
void DisableSerializationTimeoutCheck()
{
isSerializationTimeoutCheckEnabled_ = false;
}
bool IsSerializationTimeoutCheckEnabled()
{
return isSerializationTimeoutCheckEnabled_;
}
void SetSerializationCheckThreshold(int threshold)
{
serializationCheckThreshold_ = threshold;
}
int32_t GetSerializationCheckThreshold() const
{
return serializationCheckThreshold_;
}
static void AddJsDebuggerManager(int tid, JsDebuggerManager *jsDebuggerManager);
static JsDebuggerManager* GetJsDebuggerManager(int tid);
@ -231,6 +256,11 @@ private:
NotificationManager notificationManager_;
HotReloadManager hotReloadManager_;
// Serialization / DeSerialization Timeout check
bool isSerializationTimeoutCheckEnabled_ { false };
// in milliseconds
static constexpr int32_t DEFAULT_THRESHOLD = 8;
int32_t serializationCheckThreshold_ { DEFAULT_THRESHOLD };
static std::unordered_map<int, JsDebuggerManager *> jsDebuggerManagerMap_;
static std::shared_mutex mutex_;

View File

@ -20,6 +20,7 @@
#include "ecmascript/builtins/builtins_ark_tools.h"
#include "ecmascript/checkpoint/thread_state_transition.h"
#include "ecmascript/debugger/debugger_api.h"
#include "ecmascript/debugger/js_debugger_manager.h"
#include "ecmascript/dfx/hprof/heap_profiler.h"
#include "ecmascript/dfx/stackinfo/js_stackinfo.h"
#include "ecmascript/dfx/tracing/tracing.h"
@ -719,6 +720,17 @@ void DFXJSNApi::SetCpuSamplingInterval([[maybe_unused]] const EcmaVM *vm, [[mayb
#endif
}
void DFXJSNApi::EnableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM, int32_t threshold)
{
ecmaVM->GetJsDebuggerManager()->EnableSerializationTimeoutCheck();
ecmaVM->GetJsDebuggerManager()->SetSerializationCheckThreshold(threshold);
}
void DFXJSNApi::DisableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM)
{
ecmaVM->GetJsDebuggerManager()->DisableSerializationTimeoutCheck();
}
bool DFXJSNApi::SuspendVM([[maybe_unused]] const EcmaVM *vm)
{
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)

View File

@ -120,6 +120,8 @@ public:
static void StartCpuProfilerForInfo(const EcmaVM *vm,
int interval = 500); // 500:Default Sampling interval 500 microseconds
static std::unique_ptr<ProfileInfo> StopCpuProfilerForInfo(const EcmaVM *vm);
static void EnableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM, int32_t threshhold);
static void DisableSeriliazationTimeoutCheck(const EcmaVM *ecmaVM);
enum class PUBLIC_API ProfilerType : uint8_t { CPU_PROFILER, HEAP_PROFILER };

View File

@ -1435,6 +1435,7 @@ private:
static bool IsWeak(const EcmaVM *vm, uintptr_t localAddress);
static void DisposeGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr);
static bool IsAotEscape();
static bool IsSerializationTimeoutCheckEnabled(const EcmaVM *vm);
template<typename T>
friend class Global;
template<typename T>

View File

@ -3767,6 +3767,21 @@ bool JSNApi::IsJitEscape()
escapeMap[CrashType::JS] >= CrashInfo::GetJsCrashCount();
}
bool JSNApi::IsSerializationTimeoutCheckEnabled(const EcmaVM *vm)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false);
ecmascript::ThreadManagedScope scope(thread);
// Currently only log trace on main thread
if (!thread->IsMainThread()) {
return false;
}
auto jsDebuggerManager = vm->GetJsDebuggerManager();
if (jsDebuggerManager != nullptr) {
return jsDebuggerManager->IsDebugApp() && jsDebuggerManager->IsSerializationTimeoutCheckEnabled();
}
return false;
}
void JSNApi::LoadAotFile(EcmaVM *vm, const std::string &moduleName)
{
if (IsAotEscape()) {
@ -4121,11 +4136,29 @@ void *JSNApi::SerializeValue(const EcmaVM *vm, Local<JSValueRef> value, Local<JS
JSHandle<JSTaggedValue> arkTransfer = JSNApiHelper::ToJSHandle(transfer);
JSHandle<JSTaggedValue> arkCloneList = JSNApiHelper::ToJSHandle(cloneList);
#if ECMASCRIPT_ENABLE_VALUE_SERIALIZER
bool serializationTimeoutCheckEnabled = IsSerializationTimeoutCheckEnabled(vm);
std::chrono::system_clock::time_point startTime;
std::chrono::system_clock::time_point endTime;
if (serializationTimeoutCheckEnabled) {
startTime = std::chrono::system_clock::now();
}
ecmascript::ValueSerializer serializer(thread, defaultTransfer, defaultCloneShared);
std::unique_ptr<ecmascript::SerializeData> data;
if (serializer.WriteValue(thread, arkValue, arkTransfer, arkCloneList)) {
data = serializer.Release();
}
if (serializationTimeoutCheckEnabled) {
endTime = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
auto threshold = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::milliseconds(vm->GetJsDebuggerManager()->GetSerializationCheckThreshold())).count();
if (duration >= threshold) {
std::stringstream tagMsg;
tagMsg << "SerializationTimeout::tid=" << thread->GetThreadId();
tagMsg << ";task=serialization;duration=" << duration;
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, tagMsg.str());
}
}
if (data == nullptr) {
return nullptr;
} else {
@ -4152,7 +4185,25 @@ Local<JSValueRef> JSNApi::DeserializeValue(const EcmaVM *vm, void *recoder, void
#if ECMASCRIPT_ENABLE_VALUE_SERIALIZER
std::unique_ptr<ecmascript::SerializeData> data(reinterpret_cast<ecmascript::SerializeData *>(recoder));
ecmascript::BaseDeserializer deserializer(thread, data.release(), hint);
bool serializationTimeoutCheckEnabled = IsSerializationTimeoutCheckEnabled(vm);
std::chrono::system_clock::time_point startTime;
std::chrono::system_clock::time_point endTime;
if (serializationTimeoutCheckEnabled) {
startTime = std::chrono::system_clock::now();
}
JSHandle<JSTaggedValue> result = deserializer.ReadValue();
if (serializationTimeoutCheckEnabled) {
endTime = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
auto threshold = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::milliseconds(vm->GetJsDebuggerManager()->GetSerializationCheckThreshold())).count();
if (duration >= threshold) {
std::stringstream tagMsg;
tagMsg << "DeserializationTimeout::tid=" << thread->GetThreadId();
tagMsg << ";task=deserialization;duration=" << duration;
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, tagMsg.str());
}
}
return JSNApiHelper::ToLocal<ObjectRef>(result);
#else
std::unique_ptr<ecmascript::SerializationData> data(reinterpret_cast<ecmascript::SerializationData *>(recoder));