1# Debugging and Profiling JS Code Using JSVM-API
2
3## Introduction
4
5JSVM-API provide APIs for retrieving JavaScript virtual machine (JSVM) instances and performing memory analysis, profiling, and debugging, which facilitates code optimization and improves development efficiency.
6
7## Basic Concepts
8
9- JSVM: A JSVM is an environment for executing JavaScript (JS) code. It parses and executes JS code, manages memory, and provides interaction with other system resources. For example, you can use **OH_JSVM_GetVM** to retrieve JSVM instances in a specific environment. This is one of the basic JSVM management operations.
10- Debug: As an important activity in program development, debugging involves locating, analyzing, and rectifying code errors. For example, you can use **OH_JSVM_OpenInspector** to open inspector, a tool used to debug JS code, on a host and port and view the running status of an application on a real-time basis. You can use **OH_JSVM_CloseInspector** to close inspector.
11
12## Available APIs
13
14| API                      | Description                      |
15|----------------------------|--------------------------------|
16| OH_JSVM_GetVM              |  Obtains a VM instance.|
17| OH_JSVM_GetHeapStatistics  |  Obtains heap statistics of a VM.|
18| OH_JSVM_StartCpuProfiler   |  Creates and starts a CPU profiler instance.|
19| OH_JSVM_StopCpuProfiler    |  Stops the CPU profiler and outputs the result to a stream.|
20| OH_JSVM_TakeHeapSnapshot   |  Obtains a snapshot of the current heap and outputs it to a stream.|
21| OH_JSVM_OpenInspector      |  Opens an inspector instance on the specified host and port for debugging JS code.|
22| OH_JSVM_CloseInspector     |  Closes all remaining inspector connections.|
23| OH_JSVM_WaitForDebugger    |  Waits for the host to set up a socket connection with an inspector. After the connection is set up, the application continues to run. You can use **Runtime.runIfWaitingForDebugger** to run paused targets.|
24
25## Example
26
27If you are just starting out with JSVM-API, see [JSVM-API Development Process](use-jsvm-process.md). The following demonstrates only the C++ code involved in debugging and profiling JS code.
28
29### OH_JSVM_GetVM
30
31Use **OH_JSVM_GetVM** to obtain a VM instance.
32
33CPP code:
34
35```cpp
36// hello.cpp
37#include "napi/native_api.h"
38#include "ark_runtime/jsvm.h"
39#include <hilog/log.h>
40
41// Define OH_JSVM_GetVM.
42static JSVM_Value GetVM(JSVM_Env env, JSVM_CallbackInfo info)
43{
44    // Obtain a VM instance for subsequent VM-related operations or analysis.
45    JSVM_VM testVm;
46    JSVM_Status status = OH_JSVM_GetVM(env, &testVm);
47    JSVM_Value result = nullptr;
48    if (status != JSVM_OK || testVm == nullptr) {
49        OH_LOG_ERROR(LOG_APP, "JSVM OH_JSVM_GetVM: failed");
50        OH_JSVM_GetBoolean(env, true, &result);
51    } else {
52        OH_LOG_INFO(LOG_APP, "JSVM OH_JSVM_GetVM: success");
53        OH_JSVM_GetBoolean(env, false, &result);
54    }
55    return result;
56}
57// Register the GetVM callback.
58static JSVM_CallbackStruct param[] = {
59    {.data = nullptr, .callback = GetVM},
60};
61static JSVM_CallbackStruct *method = param;
62// Set a property descriptor named getVM and associate it with a callback. This allows the GetVM callback to be called from JS.
63static JSVM_PropertyDescriptor descriptor[] = {
64    {"getVM", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
65};
66```
67
68// Call C++ code from JS.
69
70```c++
71const char *srcCallNative = R"JS(getVM())JS";
72```
73
74### OH_JSVM_GetHeapStatistics
75
76Use **OH_JSVM_GetHeapStatistics** to obtain heap statistics of a VM.
77
78CPP code:
79
80```cpp
81// hello.cpp
82#include "napi/native_api.h"
83#include "ark_runtime/jsvm.h"
84#include <hilog/log.h>
85
86// Define OH_JSVM_GetHeapStatistics.
87void PrintHeapStatistics(JSVM_HeapStatistics result)
88{
89    OH_LOG_INFO(LOG_APP, "JSVM API heap totalHeapSize: %{public}zu", result.totalHeapSize);
90    OH_LOG_INFO(LOG_APP, "JSVM API heap totalHeapSizeExecutable: %{public}zu", result.totalHeapSizeExecutable);
91    OH_LOG_INFO(LOG_APP, "JSVM API heap totalPhysicalSize: %{public}zu", result.totalPhysicalSize);
92    OH_LOG_INFO(LOG_APP, "JSVM API heap totalAvailableSize: %{public}zu", result.totalAvailableSize);
93    OH_LOG_INFO(LOG_APP, "JSVM API heap usedHeapSize: %{public}zu", result.usedHeapSize);
94    OH_LOG_INFO(LOG_APP, "JSVM API heap heapSizeLimit: %{public}zu", result.heapSizeLimit);
95    OH_LOG_INFO(LOG_APP, "JSVM API heap mallocedMemory: %{public}zu", result.mallocedMemory);
96    OH_LOG_INFO(LOG_APP, "JSVM API heap externalMemory: %{public}zu", result.externalMemory);
97    OH_LOG_INFO(LOG_APP, "JSVM API heap peakMallocedMemory: %{public}zu", result.peakMallocedMemory);
98    OH_LOG_INFO(LOG_APP, "JSVM API heap numberOfNativeContexts: %{public}zu", result.numberOfNativeContexts);
99    OH_LOG_INFO(LOG_APP, "JSVM API heap numberOfDetachedContexts: %{public}zu", result.numberOfDetachedContexts);
100    OH_LOG_INFO(LOG_APP, "JSVM API heap totalGlobalHandlesSize: %{public}zu", result.totalGlobalHandlesSize);
101    OH_LOG_INFO(LOG_APP, "JSVM API heap usedGlobalHandlesSize: %{public}zu", result.usedGlobalHandlesSize);
102}
103
104static JSVM_Value GetHeapStatistics(JSVM_Env env, JSVM_CallbackInfo info)
105{
106    // Obtain the VM instance.
107    JSVM_VM testVm;
108    OH_JSVM_GetVM(env, &testVm);
109    // Obtain the heap statistics of the VM.
110    JSVM_HeapStatistics result;
111    OH_JSVM_GetHeapStatistics(testVm, &result);
112    // Print VM heap statistics.
113    PrintHeapStatistics(result);
114    // Return the number of local contexts in the VM heap statistics.
115    JSVM_Value nativeContextsCnt = nullptr;
116    OH_JSVM_CreateInt64(env, result.numberOfNativeContexts, &nativeContextsCnt);
117    return nativeContextsCnt;
118}
119// Register the GetHeapStatistics callback.
120static JSVM_CallbackStruct param[] = {
121    {.data = nullptr, .callback = GetHeapStatistics},
122};
123static JSVM_CallbackStruct *method = param;
124// Set a property descriptor named getHeapStatistics and associate it with a callback. This allows the GetHeapStatistics callback to be called from JS.
125static JSVM_PropertyDescriptor descriptor[] = {
126    {"getHeapStatistics", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT},
127};
128```
129
130// Call C++ code from JS.
131
132```c++
133const char *srcCallNative = R"JS(getHeapStatistics())JS";
134```
135
136For details about the sample code of the previous APIs, see:
137
138[JSVM Debugging and Profiling](jsvm-debugger-cpuprofiler-heapsnapshot.md)
139
140### OH_JSVM_StartCpuProfiler
141
142Use **OH_JSVM_StartCpuProfiler** to create and start a CPU profiler instance.
143
144### OH_JSVM_StopCpuProfiler
145
146Use **OH_JSVM_StopCpuProfiler** to stop the CPU profiler and output the result to a stream.
147
148### OH_JSVM_TakeHeapSnapshot
149
150Use **OH_JSVM_TakeHeapSnapshot** to obtain a snapshot of the current heap and output it to a stream.
151
152### OH_JSVM_OpenInspector
153
154Use **OH_JSVM_OpenInspector** to open an inspector instance on the specified host and port for debugging JS code.
155
156### OH_JSVM_CloseInspector
157
158Use **OH_JSVM_CloseInspector** to close all remaining inspector connections.
159
160### OH_JSVM_WaitForDebugger
161
162Use **OH_JSVM_WaitForDebugger** to wait for the host to set up a socket connection with an inspector. After the connection is set up, the application continues to run. You can use **Runtime.runIfWaitingForDebugger** to run paused targets.
163
164