mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 16:13:49 +00:00
fix dump
Signed-off-by: z00522183 <zhanheng2@huawei.com> Change-Id: I017e19b6d7c47a5017267084d55b2186c743c8ea
This commit is contained in:
parent
658530428e
commit
eca99a40c8
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include "ecmascript/dfx/hprof/heap_profiler.h"
|
||||
|
||||
#include "ecmascript/checkpoint/thread_state_transition.h"
|
||||
@ -25,6 +26,7 @@
|
||||
#include "ecmascript/mem/concurrent_sweeper.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/mem/shared_heap/shared_concurrent_sweeper.h"
|
||||
#include "ecmascript/base/block_hook_scope.h"
|
||||
|
||||
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
||||
#include "faultloggerd_client.h"
|
||||
@ -135,7 +137,8 @@ void HeapProfiler::UpdateHeapObjects(HeapSnapshot *snapshot)
|
||||
|
||||
void HeapProfiler::DumpHeapSnapshot([[maybe_unused]] DumpFormat dumpFormat, [[maybe_unused]] bool isVmMode,
|
||||
[[maybe_unused]] bool isPrivate, [[maybe_unused]] bool captureNumericValue,
|
||||
[[maybe_unused]] bool isFullGC, [[maybe_unused]] bool isSimplify)
|
||||
[[maybe_unused]] bool isFullGC, [[maybe_unused]] bool isSimplify,
|
||||
[[maybe_unused]] bool isSync)
|
||||
{
|
||||
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
||||
// Write in faultlog for heap leak.
|
||||
@ -145,22 +148,17 @@ void HeapProfiler::DumpHeapSnapshot([[maybe_unused]] DumpFormat dumpFormat, [[ma
|
||||
return;
|
||||
}
|
||||
FileDescriptorStream stream(fd);
|
||||
DumpHeapSnapshot(dumpFormat, &stream, nullptr, isVmMode, isPrivate, captureNumericValue, isFullGC, isSimplify);
|
||||
DumpHeapSnapshot(
|
||||
dumpFormat, &stream, nullptr, isVmMode, isPrivate, captureNumericValue, isFullGC, isSimplify, isSync);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool HeapProfiler::DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progress *progress,
|
||||
bool isVmMode, bool isPrivate, bool captureNumericValue,
|
||||
bool isFullGC, bool isSimplify)
|
||||
bool HeapProfiler::DoDump(DumpFormat dumpFormat, Stream *stream, Progress *progress,
|
||||
bool isVmMode, bool isPrivate, bool captureNumericValue, bool isFullGC, bool isSimplify)
|
||||
{
|
||||
int32_t heapCount = 0;
|
||||
HeapSnapshot *snapshot = nullptr;
|
||||
{
|
||||
if (isFullGC) {
|
||||
[[maybe_unused]] bool heapClean = ForceFullGC(vm_);
|
||||
ASSERT(heapClean);
|
||||
}
|
||||
LOG_ECMA(INFO) << "HeapProfiler DumpSnapshot start";
|
||||
if (isFullGC) {
|
||||
size_t heapSize = vm_->GetHeap()->GetLiveObjectSize();
|
||||
LOG_ECMA(INFO) << "HeapProfiler DumpSnapshot heap size " << heapSize;
|
||||
@ -170,7 +168,7 @@ bool HeapProfiler::DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progr
|
||||
}
|
||||
}
|
||||
snapshot = MakeHeapSnapshot(SampleType::ONE_SHOT, isVmMode, isPrivate, captureNumericValue,
|
||||
false, isFullGC, isSimplify);
|
||||
false, false, isSimplify);
|
||||
ASSERT(snapshot != nullptr);
|
||||
}
|
||||
entryIdMap_->UpdateEntryIdMap(snapshot);
|
||||
@ -189,6 +187,67 @@ bool HeapProfiler::DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progr
|
||||
return serializerResult;
|
||||
}
|
||||
|
||||
static void WaitProcess(pid_t pid)
|
||||
{
|
||||
time_t startTime = time(nullptr);
|
||||
constexpr int DUMP_TIME_OUT = 300;
|
||||
constexpr int DEFAULT_SLEEP_TIME = 100000;
|
||||
while (true) {
|
||||
int status = 0;
|
||||
pid_t p = waitpid(pid, &status, WNOHANG);
|
||||
if (p < 0 || p == pid) {
|
||||
break;
|
||||
}
|
||||
if (time(nullptr) > startTime + DUMP_TIME_OUT) {
|
||||
LOG_GC(ERROR) << "DumpHeapSnapshot kill thread, wait " << DUMP_TIME_OUT << " s";
|
||||
kill(pid, SIGTERM);
|
||||
break;
|
||||
}
|
||||
usleep(DEFAULT_SLEEP_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
bool HeapProfiler::DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progress *progress,
|
||||
bool isVmMode, bool isPrivate, bool captureNumericValue,
|
||||
bool isFullGC, bool isSimplify, bool isSync)
|
||||
{
|
||||
bool res = false;
|
||||
if (isFullGC) {
|
||||
[[maybe_unused]] bool heapClean = ForceFullGC(vm_);
|
||||
ASSERT(heapClean);
|
||||
}
|
||||
pid_t pid = -1;
|
||||
{
|
||||
base::BlockHookScope blockScope;
|
||||
ThreadManagedScope managedScope(vm_->GetJSThread());
|
||||
// suspend All.
|
||||
SuspendAllScope suspendScope(vm_->GetAssociatedJSThread());
|
||||
if (isFullGC) {
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
const_cast<Heap *>(vm_->GetHeap())->Prepare();
|
||||
}
|
||||
// fork
|
||||
if ((pid = fork()) < 0) {
|
||||
LOG_ECMA(ERROR) << "DumpHeapSnapshot fork failed!";
|
||||
return false;
|
||||
}
|
||||
if (pid == 0) {
|
||||
res = DoDump(dumpFormat, stream, progress, isVmMode, isPrivate, captureNumericValue, isFullGC, isSimplify);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
if (pid != 0) {
|
||||
if (isSync) {
|
||||
WaitProcess(pid);
|
||||
} else {
|
||||
std::thread thread(&WaitProcess, pid);
|
||||
thread.detach();
|
||||
}
|
||||
stream->EndOfStream();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool HeapProfiler::StartHeapTracking(double timeInterval, bool isVmMode, Stream *stream,
|
||||
bool traceAllocation, bool newThread)
|
||||
{
|
||||
|
@ -78,10 +78,10 @@ public:
|
||||
*/
|
||||
bool DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progress *progress = nullptr,
|
||||
bool isVmMode = true, bool isPrivate = false, bool captureNumericValue = false,
|
||||
bool isFullGC = true, bool isSimplify = false) override;
|
||||
bool isFullGC = true, bool isSimplify = false, bool isSync = true) override;
|
||||
void DumpHeapSnapshot(DumpFormat dumpFormat, bool isVmMode = true, bool isPrivate = false,
|
||||
bool captureNumericValue = false, bool isFullGC = true,
|
||||
bool isSimplify = false) override;
|
||||
bool isSimplify = false, bool isSync = true) override;
|
||||
void AddSnapshot(HeapSnapshot *snapshot);
|
||||
|
||||
bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr,
|
||||
@ -120,8 +120,9 @@ private:
|
||||
*/
|
||||
HeapSnapshot *MakeHeapSnapshot(SampleType sampleType, bool isVmMode = true,
|
||||
bool isPrivate = false, bool captureNumericValue = false,
|
||||
bool traceAllocation = false, bool isFullGC = true,
|
||||
bool isSimplify = false);
|
||||
bool traceAllocation = false, bool isFullGC = true, bool isSimplify = false);
|
||||
bool DoDump(DumpFormat dumpFormat, Stream *stream, Progress *progress,
|
||||
bool isVmMode, bool isPrivate, bool captureNumericValue, bool isFullGC, bool isSimplify);
|
||||
std::string GenDumpFileName(DumpFormat dumpFormat);
|
||||
CString GetTimeStamp();
|
||||
void UpdateHeapObjects(HeapSnapshot *snapshot);
|
||||
|
@ -42,11 +42,11 @@ public:
|
||||
virtual void MoveEvent(uintptr_t address, TaggedObject *forwardAddress, size_t size)= 0;
|
||||
virtual bool DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progress *progress = nullptr,
|
||||
bool isVmMode = true, bool isPrivate = false, bool captureNumericValue = false,
|
||||
bool isFullGC = true, bool isSimplify = false) = 0;
|
||||
bool isFullGC = true, bool isSimplify = false, bool isSync = true) = 0;
|
||||
// Provide an internal interface for oom dump.
|
||||
virtual void DumpHeapSnapshot(DumpFormat dumpFormat, bool isVmMode = true, bool isPrivate = false,
|
||||
bool captureNumericValue = false, bool isFullGC = true,
|
||||
bool isSimplify = false) = 0;
|
||||
bool isSimplify = false, bool isSync = true) = 0;
|
||||
|
||||
virtual bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr,
|
||||
bool traceAllocation = false, bool newThread = true) = 0;
|
||||
|
@ -64,18 +64,18 @@ public:
|
||||
|
||||
bool DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progress *progress = nullptr,
|
||||
bool isVmMode = true, bool isPrivate = false, bool captureNumericValue = false,
|
||||
bool isFullGC = true, bool isSimplify = false) override
|
||||
bool isFullGC = true, bool isSimplify = false, bool isSync = false) override
|
||||
{
|
||||
return profiler_->DumpHeapSnapshot(dumpFormat, stream, progress, isVmMode, isPrivate, captureNumericValue,
|
||||
isFullGC, isSimplify);
|
||||
isFullGC, isSimplify, isSync);
|
||||
}
|
||||
|
||||
void DumpHeapSnapshot(DumpFormat dumpFormat, bool isVmMode = true, bool isPrivate = false,
|
||||
bool captureNumericValue = false, bool isFullGC = true,
|
||||
bool isSimplify = false) override
|
||||
bool isSimplify = false, bool isSync = false) override
|
||||
{
|
||||
profiler_->DumpHeapSnapshot(dumpFormat, isVmMode, isPrivate, captureNumericValue,
|
||||
isFullGC, isSimplify);
|
||||
isFullGC, isSimplify, isSync);
|
||||
}
|
||||
|
||||
bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr,
|
||||
|
@ -1084,7 +1084,7 @@ void Heap::DumpHeapSnapshotBeforeOOM([[maybe_unused]] bool isFullGC)
|
||||
<< " value:" << std::to_string(pid);
|
||||
}
|
||||
// Vm should always allocate young space successfully. Really OOM will occur in the non-young spaces.
|
||||
heapProfile->DumpHeapSnapshot(DumpFormat::JSON, true, false, false, isFullGC, true);
|
||||
heapProfile->DumpHeapSnapshot(DumpFormat::JSON, true, false, false, isFullGC, true, true);
|
||||
HeapProfilerInterface::Destroy(ecmaVm_);
|
||||
#endif // ENABLE_DUMP_IN_FAULTLOG
|
||||
#endif // ECMASCRIPT_SUPPORT_SNAPSHOT
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "ecmascript/mem/shared_heap/shared_concurrent_sweeper.h"
|
||||
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
#include <sys/wait.h>
|
||||
#include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
|
||||
#include "ecmascript/dfx/cpu_profiler/samples_record.h"
|
||||
#endif
|
||||
@ -83,7 +82,7 @@ void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unus
|
||||
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
||||
const_cast<EcmaVM *>(vm));
|
||||
heapProfile->DumpHeapSnapshot(ecmascript::DumpFormat(dumpFormat), stream, progress,
|
||||
isVmMode, isPrivate, captureNumericValue, isFullGC);
|
||||
isVmMode, isPrivate, captureNumericValue, isFullGC, false, true);
|
||||
#else
|
||||
LOG_ECMA(ERROR) << "Not support arkcompiler heap snapshot";
|
||||
#endif
|
||||
@ -122,28 +121,6 @@ bool DFXJSNApi::ForceFullGC(const EcmaVM *vm)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
||||
static void WaitProcess(pid_t pid)
|
||||
{
|
||||
time_t startTime = time(nullptr);
|
||||
constexpr int DUMP_TIME_OUT = 30;
|
||||
constexpr int DEFAULT_SLEEP_TIME = 100000;
|
||||
while (true) {
|
||||
int status = 0;
|
||||
pid_t p = waitpid(pid, &status, WNOHANG);
|
||||
if (p < 0 || p == pid) {
|
||||
break;
|
||||
}
|
||||
if (time(nullptr) > startTime + DUMP_TIME_OUT) {
|
||||
LOG_GC(ERROR) << "wait " << DUMP_TIME_OUT << " s";
|
||||
kill(pid, SIGTERM);
|
||||
break;
|
||||
}
|
||||
usleep(DEFAULT_SLEEP_TIME);
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_DUMP_IN_FAULTLOG
|
||||
|
||||
void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
|
||||
[[maybe_unused]] bool isVmMode, [[maybe_unused]] bool isPrivate,
|
||||
[[maybe_unused]] bool captureNumericValue, [[maybe_unused]] bool isFullGC)
|
||||
@ -161,37 +138,19 @@ void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unus
|
||||
vm->GetJSThread()->SetStackTraceFd(stackTraceFd);
|
||||
}
|
||||
}
|
||||
if (isFullGC) {
|
||||
[[maybe_unused]] bool heapClean = ForceFullGC(vm);
|
||||
ASSERT(heapClean);
|
||||
}
|
||||
ecmascript::base::BlockHookScope blockScope;
|
||||
// suspend All.
|
||||
ecmascript::SuspendAllScope suspendScope(vm->GetAssociatedJSThread());
|
||||
if (isFullGC) {
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
const_cast<ecmascript::Heap *>(vm->GetHeap())->Prepare();
|
||||
}
|
||||
// fork
|
||||
pid_t pid = -1;
|
||||
if ((pid = fork()) < 0) {
|
||||
LOG_ECMA(ERROR) << "DumpHeapSnapshot fork failed!";
|
||||
|
||||
// Write in faultlog for heap leak.
|
||||
int32_t fd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_HEAP_SNAPSHOT));
|
||||
if (fd < 0) {
|
||||
LOG_ECMA(ERROR) << "Write FD failed, fd" << fd;
|
||||
return;
|
||||
}
|
||||
if (pid == 0) {
|
||||
// Write in faultlog for heap leak.
|
||||
int32_t fd = RequestFileDescriptor(static_cast<int32_t>(FaultLoggerType::JS_HEAP_SNAPSHOT));
|
||||
if (fd < 0) {
|
||||
LOG_ECMA(ERROR) << "Write FD failed, fd" << fd;
|
||||
return;
|
||||
}
|
||||
FileDescriptorStream stream(fd);
|
||||
DumpHeapSnapshot(vm, dumpFormat, &stream, nullptr, isVmMode, isPrivate, captureNumericValue, false);
|
||||
_exit(0);
|
||||
} else {
|
||||
std::thread thread(&WaitProcess, pid);
|
||||
thread.detach();
|
||||
}
|
||||
FileDescriptorStream stream(fd);
|
||||
ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(
|
||||
const_cast<EcmaVM *>(vm));
|
||||
heapProfile->DumpHeapSnapshot(ecmascript::DumpFormat(dumpFormat), &stream, nullptr,
|
||||
isVmMode, isPrivate, captureNumericValue, isFullGC, false, false);
|
||||
|
||||
sem_post(&g_heapdumpCnt);
|
||||
#endif // ENABLE_DUMP_IN_FAULTLOG
|
||||
#else
|
||||
@ -213,14 +172,13 @@ void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unus
|
||||
sem_init(&g_heapdumpCnt, 0, THREAD_COUNT);
|
||||
uint32_t curTid = vm->GetTid();
|
||||
LOG_ECMA(INFO) << "DumpHeapSnapshot tid " << tid << " curTid " << curTid;
|
||||
if ((tid == 0) || ((tid != 0) && (tid == curTid))) {
|
||||
DumpHeapSnapshotWithVm(vm, dumpFormat, isVmMode, isPrivate, captureNumericValue, isFullGC);
|
||||
}
|
||||
DumpHeapSnapshotWithVm(vm, dumpFormat, isVmMode, isPrivate, captureNumericValue, isFullGC, tid);
|
||||
}
|
||||
|
||||
void DFXJSNApi::DumpHeapSnapshotWithVm([[maybe_unused]] const EcmaVM *vm, [[maybe_unused]] int dumpFormat,
|
||||
[[maybe_unused]] bool isVmMode, [[maybe_unused]] bool isPrivate,
|
||||
[[maybe_unused]] bool captureNumericValue, [[maybe_unused]] bool isFullGC)
|
||||
[[maybe_unused]] bool captureNumericValue, [[maybe_unused]] bool isFullGC,
|
||||
[[maybe_unused]] uint32_t tid)
|
||||
{
|
||||
#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
|
||||
#if defined(ENABLE_DUMP_IN_FAULTLOG)
|
||||
@ -243,19 +201,24 @@ void DFXJSNApi::DumpHeapSnapshotWithVm([[maybe_unused]] const EcmaVM *vm, [[mayb
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
|
||||
struct DumpForSnapShotStruct *dump = static_cast<struct DumpForSnapShotStruct *>(work->data);
|
||||
DFXJSNApi::GetHeapPrepare(dump->vm);
|
||||
DumpHeapSnapshot(dump->vm, dump->dumpFormat, dump->isVmMode, dump->isPrivate,
|
||||
dump->captureNumericValue, dump->isFullGC);
|
||||
delete dump;
|
||||
delete work;
|
||||
});
|
||||
uint32_t curTid = vm->GetTid();
|
||||
int ret = 0;
|
||||
if ((tid == 0) || ((tid != 0) && (tid == curTid))) {
|
||||
ret = uv_queue_work(loop, work, [](uv_work_t *) {}, [](uv_work_t *work, int32_t) {
|
||||
struct DumpForSnapShotStruct *dump = static_cast<struct DumpForSnapShotStruct *>(work->data);
|
||||
DFXJSNApi::GetHeapPrepare(dump->vm);
|
||||
DumpHeapSnapshot(dump->vm, dump->dumpFormat, dump->isVmMode, dump->isPrivate,
|
||||
dump->captureNumericValue, dump->isFullGC);
|
||||
delete dump;
|
||||
delete work;
|
||||
});
|
||||
}
|
||||
|
||||
// dump worker vm
|
||||
const_cast<EcmaVM *>(vm)->EnumerateWorkerVm([&](const EcmaVM *workerVm) -> void {
|
||||
uint32_t curTid = workerVm->GetTid();
|
||||
LOG_ECMA(INFO) << "DumpHeapSnapshot workthread curTid " << curTid;
|
||||
DumpHeapSnapshotWithVm(workerVm, dumpFormat, isVmMode, isPrivate, captureNumericValue, isFullGC);
|
||||
DumpHeapSnapshotWithVm(workerVm, dumpFormat, isVmMode, isPrivate, captureNumericValue, isFullGC, tid);
|
||||
return;
|
||||
});
|
||||
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
static void DumpHeapSnapshot(const EcmaVM *vm, int dumpFormat, bool isVmMode, bool isPrivate,
|
||||
bool captureNumericValue, bool isFullGC, uint32_t tid);
|
||||
static void DumpHeapSnapshotWithVm(const EcmaVM *vm, int dumpFormat, bool isVmMode, bool isPrivate,
|
||||
bool captureNumericValue, bool isFullGC);
|
||||
bool captureNumericValue, bool isFullGC, uint32_t tid);
|
||||
static void TriggerGC(const EcmaVM *vm, uint32_t tid);
|
||||
static bool ForceFullGC(const EcmaVM *vm);
|
||||
static void TriggerGCWithVm(const EcmaVM *vm);
|
||||
|
Loading…
Reference in New Issue
Block a user