diff --git a/en/device-dev/subsystems/figure/ABStartup_1.png b/en/device-dev/subsystems/figure/ABStartup_1.png new file mode 100644 index 0000000000000000000000000000000000000000..d6805478550aa33c3b1a403a4a8af67189c92239 Binary files /dev/null and b/en/device-dev/subsystems/figure/ABStartup_1.png differ diff --git a/en/device-dev/subsystems/figure/ABStartup_2.png b/en/device-dev/subsystems/figure/ABStartup_2.png new file mode 100644 index 0000000000000000000000000000000000000000..4853f09f0ac40b1d28c676c1aa2331ce0c996aa1 Binary files /dev/null and b/en/device-dev/subsystems/figure/ABStartup_2.png differ diff --git a/en/device-dev/subsystems/figure/ABStartup_3.png b/en/device-dev/subsystems/figure/ABStartup_3.png new file mode 100644 index 0000000000000000000000000000000000000000..fa2eb6b2105468f816d4a75200eb4f6c64fe3a2b Binary files /dev/null and b/en/device-dev/subsystems/figure/ABStartup_3.png differ diff --git a/en/device-dev/subsystems/figure/ABStartup_4.png b/en/device-dev/subsystems/figure/ABStartup_4.png new file mode 100644 index 0000000000000000000000000000000000000000..f23ea49d9fa04eb907047f43be9e9490be834089 Binary files /dev/null and b/en/device-dev/subsystems/figure/ABStartup_4.png differ diff --git a/en/device-dev/subsystems/figure/ABStartup_5.png b/en/device-dev/subsystems/figure/ABStartup_5.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f6292a2bcc9d91171428cc70a262ed740182d1 Binary files /dev/null and b/en/device-dev/subsystems/figure/ABStartup_5.png differ diff --git a/en/device-dev/subsystems/figure/ABStartup_6.png b/en/device-dev/subsystems/figure/ABStartup_6.png new file mode 100644 index 0000000000000000000000000000000000000000..7e6b11e268374f2f5c091f3b821f0e84f31f1e53 Binary files /dev/null and b/en/device-dev/subsystems/figure/ABStartup_6.png differ diff --git a/en/device-dev/subsystems/figure/ABStartup_7.png b/en/device-dev/subsystems/figure/ABStartup_7.png new file mode 100644 index 0000000000000000000000000000000000000000..21e20faa1c8d32758c1360d8c718d1c6198e7f63 Binary files /dev/null and b/en/device-dev/subsystems/figure/ABStartup_7.png differ diff --git a/en/device-dev/subsystems/figure/ABStartup_8.png b/en/device-dev/subsystems/figure/ABStartup_8.png new file mode 100644 index 0000000000000000000000000000000000000000..ec4873a2e91327170a4ab0273c2f78ececae7804 Binary files /dev/null and b/en/device-dev/subsystems/figure/ABStartup_8.png differ diff --git a/en/device-dev/subsystems/figure/HiTraceMeter.png b/en/device-dev/subsystems/figure/HiTraceMeter.png new file mode 100644 index 0000000000000000000000000000000000000000..798cbb1deb73360afd373988fd5f19427aa64f95 Binary files /dev/null and b/en/device-dev/subsystems/figure/HiTraceMeter.png differ diff --git a/en/device-dev/subsystems/subsys-boot-init-plugin.md b/en/device-dev/subsystems/subsys-boot-init-plugin.md index eb1a87af1c08fed7f0ee84f681c988bf19b37586..9f04f40f328af14e172daacafe3f1e8dc95c7bdc 100644 --- a/en/device-dev/subsystems/subsys-boot-init-plugin.md +++ b/en/device-dev/subsystems/subsys-boot-init-plugin.md @@ -2,17 +2,27 @@ ## Overview ### Basic Concepts + - Introduction to begetctl - For details, see [Description of begetctl Commands](#table14737791480). + + begetctl is a CLI-based management tool. For details about this functions, see [Description of begetctl Commands](#table14737791480). + - bootchart plug-in + The bootchart plug-in is an open source tool used to evaluate system performance during Linux startup. It automatically collects information such as the CPU usage, disk throughput, and process status, and displays the evaluation result in graphics to facilitate system startup optimization. + - bootevent plug-in + + bootevent is a plug-in that records key startup events of the init process and each service. The recorded information includes the event name, startup time of the service associated with the event, and event occurrence time. By using the exported file for trace parsing, you can then optimize the system startup process. + ### Constraints -bootchart is available only for the standard system, and begetctl is available for both the small system and the standard system. +bootchart and bootevent are available only for the standard system, and begetctl is available for both the small system and the standard system. + +## How to Develop -## Development Guidelines ### Parameters + **Table 1** Description of begetctl commands | Command| Format and Example| Description| | :---------- | :---------- |:--------| @@ -22,7 +32,7 @@ bootchart is available only for the standard system, and begetctl is available f | param set name value| Sets system parameters.
Example:
begetctl param set ohos.servicectrl.display 1 or param set ohos.servicectrl.display 1| N/A| | param wait name [value] [timeout] | Waits for system parameters.
Example:
begetctl param wait persist.sys.usb.config hdc or param wait persist.sys.usb.config hdc| The default value of **timeout** is **30**.| | param dump [verbose] | Dumps system parameter information.
Example:
begetctl param dump or param dump| N/A| -| param shell [name] | Enters the parameter shell.
Example:
begetctl param shell or param shell| N/A| +| param shell [name] | Enters the parameter shell.
Example:
begetctl param shell or param shell| N/A| | timer_stop servicename | Stops the service timer.
Example:
begetctl timer_stop appspawn | The value of **servicename** can contain a maximum of 96 characters.| | timer_start servicename timeout | Starts the service timer.
Example:
begetctl timer_start appspawn | The value of **servicename** can contain a maximum of 96 characters. The default value of **timeout** is **10**. | | start_service servicename | Starts a service.
Example:
begetctl start_service appspawn or start_service appspawn| N/A| @@ -54,21 +64,19 @@ bootchart is available only for the standard system, and begetctl is available f | modulectl uninstall moduleName | Uninstalls a dynamic plug-in.
Example:
modulectl uninstall bootchart | N/A| | modulectl install moduleName | Installs a dynamic plug-in.
Example:
modulectl install bootchart | N/A| | modulectl list | Views the list of dynamic plug-ins.
Example:
begetctl modulectl list | N/A| +| setloglevel level | Sets the log level to **info**.
Example:
begetctl setloglevel 1 | The log level ranges from **0** to **4**.| +| getloglevel | Obtains the log level of the init process.
Example:
begetctl getloglevel | N/A| +| bootevent disable | Disables the bootevent plug-in.
Example:
begetctl bootevent disable| N/A| +| bootevent enable | Enables the bootevent plug-in.
Example:
begetctl bootevent enable| N/A| +| dump_service parameter_service trigger | Displays information about all triggers.
Example:
begetctl dump_service parameter_service trigger | N/A| +| dump_service all | Displays information about all services.
Example:
begetctl dump_service all | N/A| +| dump_service serviceName | Displays information about a single service.
Example:
begetctl dump_service param_watcher | N/A| +| dump api | Displays information about APIs of the init process.
Example:
begetctl dump api | N/A| -## How to Develop - -### Available APIs - - **Table 1** Description of plug-in management APIs -| API| Description| -| ---------- | ---------- | -| void PluginExecCmdByName(const char *name, const char *cmdContent) | Starts a plug-in by name.| -| void PluginExecCmdByCmdIndex(int index, const char *cmdContent) | Starts a plug-in by index.| -| int PluginExecCmd(const char *name, int argc, const char **argv) | Starts a plug-in by command.| -| int AddCmdExecutor(const char *cmdName, CmdExecutor execCmd) | Adds the plug-in installation command.| ### How to Develop Add a plug-in. The following uses bootchart as an example: + 1. Install the **.so** file and define an independent file to implement the following functions: ```c static int bootchartEarlyHook(int stage, int prio, void *cookie) @@ -87,11 +95,11 @@ bootchart is available only for the standard system, and begetctl is available f MODULE_CONSTRUCTOR(void) { - // Depending on parameter service + // Depends on parameter service InitAddPostPersistParamLoadHook(0, bootchartEarlyHook); } ``` -2. Compile the static library **libbootchart_static** and add it to the **static_modules** group. +2. Compile the static library **libbootchart\_static** and add it to the **static\_modules** group. ``` group("static_modules") { if (!defined(ohos_lite)) { @@ -138,19 +146,23 @@ bootchart is available only for the standard system, and begetctl is available f ### Development Example +#### Bootchart + Prerequisites + 1. Prepare the bootchart test environment. Specifically, install Python and pycairo by running **pip install pycairo** on Linux. 2. Decompress **bootchart-master.tar**. tar -zxvf bootchart-master.tar Procedure + 1. Start the system. 2. Run the **begetctl bootchart enable** command. 3. Restart the system. 4. Run the **begetctl bootchart stop** command. 5. Run the **begetctl bootchart disable** command. - 6. Export the following files from the **/data/bootchart** directory and save them to the **bootchart** folder: + 6. Export the following files from the **/data/bootchart** directory and save them to the **bootchart** folder:
header
proc_diskstats.log
proc_ps.log
@@ -161,5 +173,38 @@ bootchart is available only for the standard system, and begetctl is available f python3 pybootchartgui.py -f pdf bootchart.tgz ``` - Expected Result - A **bootchart.pdf** file is generated in the **bootchart-master** directory. + Expected result: + + A **bootchart.pdf** file is generated in the **bootchart-master** directory. + +#### bootevent + +1. Configure one or more boot events in the **.cfg** file. + + Configure a single boot event. + ```json + bootevents : "bootevent.xxxbootevent", + ``` + Configure multiple boot events. + ```json + bootevents : ["bootevent.xxxbootevent1", "bootevent.xxxbootevent2.xxx"], + ``` +> **NOTE** +> +> The configured event must start with **bootevent**. + +2. Send the boot events. + + Call the **SetParameter** API provided by init process to send the boot events. For example, to send the XXXbootevent1 event configured in the previous step, use the following code: + ```c + SetParameter("bootevent.XXXbootevent1", "true"); + ``` +3. Enable the bootevent function by running the **begetctl bootevent enable** command. + + To disable the bootevent function, run the **begetctl bootevent disable** command and restart the system. + +4. Use the exported bootevent file for trace analysis. + + - The exported bootevent file is stored in the **/data/service/el0/startup/init/** directory. + - It is named in the format of *timestamp***.bootevent**. + - You can import the file to the trace analysis tool for visual analysis. diff --git a/en/device-dev/subsystems/subsys-boot-overview.md b/en/device-dev/subsystems/subsys-boot-overview.md index fefaeb0640b6e8fb26b0a2c6670aee88d21f4dcd..1d2f8a1ae7354f4535479315f956f9b3c097a0df 100644 --- a/en/device-dev/subsystems/subsys-boot-overview.md +++ b/en/device-dev/subsystems/subsys-boot-overview.md @@ -7,7 +7,7 @@ The following figure shows the context structure of the Startup subsystem. **Figure 1** Context structure of the Startup subsystem - ![context-structure-of-the-startup-subsystem](figure/context-structure-of-the-Startup-subsystem.png) + ![context-structure-of-the-Startup-subsystem](figure/context-structure-of-the-Startup-subsystem.png) When the system is powered on, the kernel loads and starts services and applications as follows: @@ -22,27 +22,32 @@ When the system is powered on, the kernel loads and starts services and applicat The Startup subsystem consists of the following modules: -- init module
+- init module + This module corresponds to the init process, which is the first user-mode process started after the kernel is initialized. After the init process starts, it reads and parses the **init.cfg** file. Based on the parsing result, the init module executes the commands listed in Table 2 in [Job Management](../subsystems/subsys-boot-init-jobs.md) and starts the key system service processes in sequence with corresponding permissions granted. -- ueventd module
+- ueventd module + This module listens for **netlink** events about hot swap of kernel device drivers and dynamically manages the **dev** node of the corresponding device based on the event type. -- appspawn module
+- appspawn module + This module spawns application processes upon receiving commands from the foundation, configures permissions for new processes, and calls the entry function of the application framework. -- bootstrap module
+- bootstrap module + This module provides entry identifiers for starting services and features. When SAMGR is started, the entry function identified by bootstrap is called and system services are started. -- syspara module
+- syspara module + This module provides APIs for obtaining device information, such as the product name, brand name, and manufacturer name, based on the OpenHarmony Product Compatibility Specifications (PCS). It also provides APIs for setting and obtaining system attributes. ## Constraints - The source code directory of the Startup subsystem varies according to the platform. + The source code directory of the Startup subsystem varies according to the platform. - **Table 1** Directories and applicable platforms of the Startup subsystem + **Table 1** Directories and applicable platforms of the Startup subsystem | Source Code Directory| Applicable Platform| | -------- | -------- | @@ -57,7 +62,9 @@ The Startup subsystem consists of the following modules: - When porting a new chip platform, you need to add the **/vendor/etc/init/init.{hardware}.cfg** file that contains the platform-level initialization configuration. This file is used to implement platform-level initialization, for example, installing the ko driver and configuring information on the related **/proc** nodes. - > **NOTE**: The configuration file **init.cfg** must be in JSON format. + > **NOTE** + > + > The configuration file **init.cfg** must be in JSON format. - bootstrap module: The zInit code must be configured in the link script. @@ -186,7 +193,9 @@ On each development board, you need to partition the memory to store the precedi This example assumes the **system** partition as the required partition on the Hi3516D V300 platform to illustrate the boot process. During this process, the init process reads the required fstab information, creates a block device node, and mounts it to the required partition. The following provides the key code snippets and log information as reference for debugging. - > **NOTE**: The code snippets below are exhibited in the logical sequence. They are not neighboring to each other in the source code. + > **NOTE** + > + > The code snippets below are exhibited in the logical sequence. They are not neighboring to each other in the source code. 1. Obtain required device information. ``` @@ -276,10 +285,11 @@ On each development board, you need to partition the memory to store the precedi ``` The key variables in the code are as follows: - **bus**: a string that saves the path of the bus connected to the current device. - **parent**: a string that stores the device path obtained from **syspath** in the uevent message. - **links**: a pointer to the memory that stores the soft link path. - **bootDevice**: a string that stores the value of **default_boot_device** in **bootargs** + - **bus**: a string that saves the path of the bus connected to the current device. + - **parent**: a string that stores the device path obtained from **syspath** in the uevent message. + - **links**: a pointer to the memory that stores the soft link path. + - **bootDevice**: a string that stores the value of **default_boot_device** in **bootargs** + According to the code, the corresponding soft link is created for the device only when the type of the connected bus is **platform**. The path of the soft link is as follows: ``` /dev/block/platform/soc/10100000.himci.eMMC/by-name @@ -328,13 +338,141 @@ On each development board, you need to partition the memory to store the precedi - Mounting of vendor partitions -After mounting required partitions, the init process scans each script file in the **vendor** partition. The initialization scripts related to the chip or development board are named in the format of **/vendor/etc/init.{ohos.boot.hardware}.cfg**. Wherein, **/vendor/etc/fstab.{ohos.boot.hardware}** represents the extended mount partition file; **hardware** is sourced from **bootargs**, which is passed from the bootloader to the kernel. + After mounting required partitions, the init process scans each script file in the **vendor** partition. The initialization scripts related to the chip or development board are named in the format of **/vendor/etc/init.{ohos.boot.hardware}.cfg**. Wherein, **/vendor/etc/fstab.{ohos.boot.hardware}** represents the extended mount partition file; **hardware** is sourced from **bootargs**, which is passed from the bootloader to the kernel. ### Boot Loading Without ramdisk Certain development boards do not use the ramdisk boot mode. For these boards, the boot process is implemented by directly loading the **system.img** file through the kernel. In such case, you need to modify the product configuration file in **productdefine**. Specifically, you need to turn off the **enable_ramdisk** switch to disable ramdisk generation so that the init process does not boot from ramdisk to system. -The boot loading process in this scenario is similar to that in the preceding section. The only difference is as follows: If ramdisk is used, the init process mounts **system.img** to the **/usr** directory, and then switches to the **/usr** directory using **chroot** and executes the **/etc/init.cfg** script. If ramdisk is not used, there is no chroot process, and the boot script is **init.without_two_stages.cfg**. +Boot loading in this scenario is similar to that in the preceding section. The only difference is as follows: If ramdisk is used, the init process mounts **system.img** to the **/usr** directory and then switches to the **/usr** directory using **chroot**. If ramdisk is not used, the init process directly runs the **init.cfg** file. + +For boot loading without ramdisk (that is, system as root), the block device where the root file system is located is passed to the kernel through **bootargs**, for example, **root=/dev/mmcblk0p5 and rootfstype=ext4**. During initialization of the root file system, the kernel parses the **root** field in **bootargs** to complete mounting of the root file system. + + +### Partition A/B Booting + +Currently, OpenHarmony supports booting from partitions A and B (active and standby system partitions), both of which are configured in the same device storage. During the booting process, the system partition to load is determined based on the slot of the active partition. Partition A/B booting is supported only for the system partition and chipset partition. + +- bootslots + + Number of the supported boot partitions. If **bootslots** is set to **2**, the system can boot from both system partitions A and B. If **bootslots** is set to **1**, partition A/B booting is not supported and the system can boot only from the default system partition. + + In the initial phase of init process startup, the system reads the **bootslots** value to determine whether partition A/B booting is supported. If yes, the system continues to determine the system partition to mount. If not, the system mounts the system partition based on the default fstab. The API for the init process to obtain the **bootslots** value is as follows: + ``` + int GetBootSlots(void) + { + int bootSlots = GetSlotInfoFromParameter("bootslots"); + BEGET_CHECK_RETURN_VALUE(bootSlots <= 0, bootSlots); + BEGET_LOGI("No valid slot value found from parameter, try to get it from cmdline"); + return GetSlotInfoFromCmdLine("bootslots"); + } + ``` + After normal system startup, you can obtain the **bootslots** value from the system parameter **ohos.boot.bootslots** to check whether the current system supports partition A/B booting. The command for obtaining **ohos.boot.bootslots** is as follows: + ``` + param get ohos.boot.bootslots + ``` + +- currentslot + + Current system partition, for example, partition A or partition B. The value of **currentslot** is a number. For example, **1** indicates partition A, and **2** indicates partition B. + + In the initial phase of startup, the init process determines whether the system supports partition A/B booting based on **bootslots**. If the system does not support partition A/B booting, the init process directly boots from the default system partition instead of obtaining the **currentslot** value. If the system supports partition A/B booting, the init process obtains the **currentslot** value and determines whether partition A or partition B is the current system partition. The API for the init process to obtain the **currentslot** value is as follows: + ``` + int GetCurrentSlot(void) + { + // get current slot from parameter + int currentSlot = GetSlotInfoFromParameter("currentslot"); + BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot); + BEGET_LOGI("No valid slot value found from parameter, try to get it from cmdline"); + + // get current slot from cmdline + currentSlot = GetSlotInfoFromCmdLine("currentslot"); + BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot); + BEGET_LOGI("No valid slot value found from cmdline, try to get it from misc"); + + // get current slot from misc + return GetSlotInfoFromMisc(MISC_PARTITION_ACTIVE_SLOT_OFFSET, MISC_PARTITION_ACTIVE_SLOT_SIZE); + } + ``` + +- Partition A/B booting process + + 1. Obtain the **currentslot** value to determine whether partition A or partition B is the current system partition. + 2. Construct new partition mounting configuration based on the original fstab file, and add the suffix **a** or **b** to the partitions that support partition A/B booting, that is, system and chipset partitions. + 3. Mount the partition added with the corresponding suffix and enter the second phase of startup. This phase occurs in partition A or B and concludes the partition A/B booting process. + + The API for constructing new partition mounting configuration is as follows: + ``` + static void AdjustPartitionNameByPartitionSlot(FstabItem *item) + { + BEGET_CHECK_ONLY_RETURN(strstr(item->deviceName, "/system") != NULL || + strstr(item->deviceName, "/chipset") != NULL); + char buffer[MAX_BUFFER_LEN] = {0}; + int slot = GetCurrentSlot(); + BEGET_ERROR_CHECK(slot > 0 && slot <= MAX_SLOT, slot = 1, "slot value %d is invalid, set default value", slot); + BEGET_INFO_CHECK(slot > 1, return, "default partition doesn't need to add suffix"); + BEGET_ERROR_CHECK(sprintf_s(buffer, sizeof(buffer), "%s_%c", item->deviceName, 'a' + slot - 1) > 0, + return, "Failed to format partition name suffix, use default partition name"); + free(item->deviceName); + item->deviceName = strdup(buffer); + BEGET_LOGI("partition name with slot suffix: %s", item->deviceName); + } + ``` + +- Development example + + The following uses the rk3568 platform as an example to illustrate how to change from default partition booting to partition A/B booting. + + 1. Burn the original image, and view the device information of each partition. + + ![Original partition](figure/ABStartup_1.png) + + Use the original image to construct images of the partitions used for partition A/B booting, and test the partition A/B booting function. + - Copy the **system** and **vendor** images, and add the suffix **\_b** to them. + - Add partitions **system_b** and **vendor_b** to the partition table in **parameter.txt**. + + 2. Burn the images of the partitions used for partition A/B booting. + + - Import the partition configuration to the rk3568 burning tool, and select the **parameter.txt** file containing the **system_b** and **vendor_b** partitions. + - Select images (including **system_b** and **vendor_b** images) based on the new partition table configuration, and then burn the images. + + 3. After the configuration is complete, perform the following: + + 1. Run the **cat /proc/cmdline** command. If the command output contains **bootslot=2**, the system supports partition A/B booting. + + ![cmdline](figure/ABStartup_2.png) + 2. Run the **param get ohos.boot.bootslot** command. If the command output contains **2**, the **bootslot** information is successfully written to the **parameter.txt**. + + 3. Run the **ls -l /dev/block/by-name** command. If the command output contains **system_b** and **vendor_b**, device nodes are successfully created in partition B. + + ![Device information](figure/ABStartup_3.png) + + 4. Run the **df -h** command to check the partitions mounted to the system. + + ![Partition information](figure/ABStartup_4.png) + + As shown in the figure, partition **mmcblk0p6** is mounted to the root file system (represented by a slash), and partition **mmcblk0p7** is mounted to **/vendor**. Based on the command output in step 3, **mmcblk0p6** is the **system** partition, and **mmcblk0p7** is the **vendor** partition. That is, the mounted partitions are the default partitions, that is, **system** and **vendor** partitions without suffixes. In other words, partition A is the default partition. + + Next, let's try booting from partition B. + + 1) Run the **partitionslot setactive 2** command to set the slot of the active partition to **2**, that is, the slot of partition B. + + ![Partition slot configuration](figure/ABStartup_5.png) + + 2) Run the **partitionslot getslot** command to check the configured slot. + + ![View Slot](figure/ABStartup_6.png) + + If **current slot** is **2**, the slot of the active partition is successfully set to **2**. + + 3) Upon restarting, run the **df -h** command to check the partitions mounted to the system. + According to the command output, partition **mmcblk0p11** is mounted to the root file system, and partition **mmcblk0p12** is mounted to **/vendor**. + + ![Mounting information](figure/ABStartup_7.png) + + 4) Run the **ls -l /dev/block/by-name** command again. + + ![New device information](figure/ABStartup_8.png) -For the boot loading process without ramdisk, that is, system as root, the block device where the root file system is located is passed to the kernel through **bootargs**, for example, **root=/dev/mmcblk0p5 and rootfstype=ext4**. During initialization of the root file system, the kernel parses the **root** field in **bootargs** to complete mounting of the root file system. + **mmcblk0p11** corresponds to **system_b**, and **mmcblk0p12** corresponds to **vendor_b**. That is, the system is successfully booted from partition B. diff --git a/en/device-dev/subsystems/subsys-dfx-hitracemeter.md b/en/device-dev/subsystems/subsys-dfx-hitracemeter.md new file mode 100644 index 0000000000000000000000000000000000000000..e5e02d1479d2b744d92bceb0525c944e87742b08 --- /dev/null +++ b/en/device-dev/subsystems/subsys-dfx-hitracemeter.md @@ -0,0 +1,361 @@ +# HiTraceMeter + +## Introduction + +HiTraceMeter is the OpenHarmony subsystem that provides APIs to implement call chain trace throughout a service process. With HiTraceMeter, you can quickly obtain the run log specific to the call chain of a service process and locate faults in inter-device, inter-process, or inter-thread communications. HiTraceMeter supports event logging in user mode and can collect trace data in user mode and kernel mode for performance tracing and analysis. + +## Basic Concepts + +The HiTraceMeter subsystem consists of three parts: + +- JS/C++ HiTraceMeter APIs for application logging +- hitrace CLI tool for data collection +- smartperf tool for graphical data analysis + +Wherein, HiTraceMeter APIs and the hitrace CLI tool run on the device side, and the smartperf tool runs on the PC side. + +HiTraceMeter APIs are provided in C++ and JS for event logging, which aims to generate the trace data necessary for performance tracing and analysis during the development process. + +The hitrace CLI tool is used to collect trace data. It captures trace data flows and saves the data as a text file. + +The smartperf tool allows you to perform data analysis manually or use the analysis script for automated data analysis. If you want to get the data analysis done automatically, you need to supply the data file generated by the hitrace CLI tool as the input for the smartperf tool. + +Traces data is classified by trace tag or trace category. Generally, one device subsystem corresponds to one tag. The tag is passed as the **Tag** parameter to event logging APIs. When you use the hitrace CLI tool to collect trace data, only the trace data specified by the **Tag** parameter is collected. Trace data of applications is fixedly labeled as **APP Tag**, and therefore, no **Tag** parameter needs to be passed to JS APIs. The following is a list of trace tags supported by HiTraceMeter. You can view the tags in [hitrace_meter.h](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h). + +```cpp +constexpr uint64_t HITRACE_TAG_NEVER = 0; // This tag is never enabled. +constexpr uint64_t HITRACE_TAG_ALWAYS = (1ULL << 0); // This tag is always enabled. +constexpr uint64_t HITRACE_TAG_DLP_CREDENTIAL = (1ULL << 21); // This tag is dlp credential service. +constexpr uint64_t HITRACE_TAG_ACCESS_CONTROL = (1ULL << 22); // This tag is access control tag. +constexpr uint64_t HITRACE_TAG_NET = (1ULL << 23); // Net tag. +constexpr uint64_t HITRACE_TAG_NWEB = (1ULL << 24); // NWeb tag. +constexpr uint64_t HITRACE_TAG_HUKS = (1ULL << 25); // This tag is huks. +constexpr uint64_t HITRACE_TAG_USERIAM = (1ULL << 26); // This tag is useriam. +constexpr uint64_t HITRACE_TAG_DISTRIBUTED_AUDIO = (1ULL << 27); // Distributed audio tag. +constexpr uint64_t HITRACE_TAG_DLSM = (1ULL << 28); // device security level tag. +constexpr uint64_t HITRACE_TAG_FILEMANAGEMENT = (1ULL << 29); // filemanagement tag. +constexpr uint64_t HITRACE_TAG_OHOS = (1ULL << 30); // OHOS generic tag. +constexpr uint64_t HITRACE_TAG_ABILITY_MANAGER = (1ULL << 31); // Ability Manager tag. +constexpr uint64_t HITRACE_TAG_ZCAMERA = (1ULL << 32); // Camera module tag. +constexpr uint64_t HITRACE_TAG_ZMEDIA = (1ULL << 33); // Media module tag. +constexpr uint64_t HITRACE_TAG_ZIMAGE = (1ULL << 34); // Image module tag. +constexpr uint64_t HITRACE_TAG_ZAUDIO = (1ULL << 35); // Audio module tag. +constexpr uint64_t HITRACE_TAG_DISTRIBUTEDDATA = (1ULL << 36); // Distributeddata manager module tag. +constexpr uint64_t HITRACE_TAG_MDFS = (1ULL << 37); // Mobile distributed file system tag. +constexpr uint64_t HITRACE_TAG_GRAPHIC_AGP = (1ULL << 38); // Graphic module tag. +constexpr uint64_t HITRACE_TAG_ACE = (1ULL << 39); // ACE development framework tag. +constexpr uint64_t HITRACE_TAG_NOTIFICATION = (1ULL << 40); // Notification module tag. +constexpr uint64_t HITRACE_TAG_MISC = (1ULL << 41); // Notification module tag. +constexpr uint64_t HITRACE_TAG_MULTIMODALINPUT = (1ULL << 42); // Multi modal module tag. +constexpr uint64_t HITRACE_TAG_SENSORS = (1ULL << 43); // Sensors mudule tag. +constexpr uint64_t HITRACE_TAG_MSDP = (1ULL << 44); // Multimodal Sensor Data Platform module tag. +constexpr uint64_t HITRACE_TAG_DSOFTBUS = (1ULL << 45); // Distributed Softbus tag. +constexpr uint64_t HITRACE_TAG_RPC = (1ULL << 46); // RPC and IPC tag. +constexpr uint64_t HITRACE_TAG_ARK = (1ULL << 47); // ARK tag. +constexpr uint64_t HITRACE_TAG_WINDOW_MANAGER = (1ULL << 48); // window manager tag. +constexpr uint64_t HITRACE_TAG_ACCOUNT_MANAGER = (1ULL << 49); // account manager tag. +constexpr uint64_t HITRACE_TAG_DISTRIBUTED_SCREEN = (1ULL << 50); // Distributed screen tag. +constexpr uint64_t HITRACE_TAG_DISTRIBUTED_CAMERA = (1ULL << 51); // Distributed camera tag. +constexpr uint64_t HITRACE_TAG_DISTRIBUTED_HARDWARE_FWK = (1ULL << 52); // Distributed hardware fwk tag. +constexpr uint64_t HITRACE_TAG_GLOBAL_RESMGR = (1ULL << 53); // Global resource manager tag. +constexpr uint64_t HITRACE_TAG_DEVICE_MANAGER = (1ULL << 54); // Distributed hardware devicemanager tag. +constexpr uint64_t HITRACE_TAG_SAMGR = (1ULL << 55); // SA tag. +constexpr uint64_t HITRACE_TAG_POWER = (1ULL << 56); // power manager tag. +constexpr uint64_t HITRACE_TAG_DISTRIBUTED_SCHEDULE = (1ULL << 57); // Distributed schedule tag. +constexpr uint64_t HITRACE_TAG_DEVICE_PROFILE = (1ULL << 58); // device profile tag. +constexpr uint64_t HITRACE_TAG_DISTRIBUTED_INPUT = (1ULL << 59); // Distributed input tag. +constexpr uint64_t HITRACE_TAG_BLUETOOTH = (1ULL << 60); // bluetooth tag. +constexpr uint64_t HITRACE_TAG_ACCESSIBILITY_MANAGER = (1ULL << 61); // accessibility manager tag. +constexpr uint64_t HITRACE_TAG_APP = (1ULL << 62); // App tag. + +constexpr uint64_t HITRACE_TAG_LAST = HITRACE_TAG_APP; +constexpr uint64_t HITRACE_TAG_NOT_READY = (1ULL << 63); // Reserved for initialization. +constexpr uint64_t HITRACE_TAG_VALID_MASK = ((HITRACE_TAG_LAST - 1) | HITRACE_TAG_LAST); +``` + +## Implementation Principle + +HiTraceMeter provides the hitrace CLI tool for capturing trace data in user mode and kernel mode, and provides C++ (innerkits) and JS (kits) APIs for event logging in user mode. Through extending kernel's ftrace functionality, HiTraceMeter can use the trace_marker node of ftrace to write the data, which is written into the user space by event logging APIs, to the kernel buffer. The following figure shows the basic HiTraceMeter architecture. + + + +![HiTraceMeter architecture](figure/HiTraceMeter.png) + + + + +## Constraints + +- The implementation of HiTraceMeter functions and APIs depends on the ftrace functionality, a framework provided by the kernel. It enables developers to add more trace functions via plug-ins. Therefore, make sure that ftrace is enabled before you use HiTraceMeter. + For most Linux kernels, ftrace is enabled by default. For details, see the ftrace documentation you may obtain. +- HiTraceMeter is available only for the mini system and standard system. + + + +# HiTraceMeter Development + +HiTraceMeter development focuses on two parts: JS/C++ event logging APIs and the hitrace CLI tool. + + + + +## When to Use + +You may encounter unexpected issues like app freezing during app development or need to view the code's call chain during code debugging. With the APIs provided by HiTraceMeter, you'll be able to trace the application delay and call chain to identify performance problems. + +## Available APIs + +Only C++ APIs are now open for system developers. If you're developing a JS app, skip this section. The following table describes the APIs applicable to the standard system. You can find the APIs in [hitrace_meter.h](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h). + +**Table 1** Sync APIs + +| API | Function |Parameter Description | +| :----------------------------------------------------------- | ------------- |------------- | +| void StartTrace(uint64_t label, const std::string& value, float limit = -1); | Starts a synchronous trace.|**label**: trace category.
**value**: trace data that indicates the specific status, such as the memory size and queue length.| +| void FinishTrace(uint64_t label); | Stops a synchronous trace.|**label**: trace category.| + + +**StartTrace** and **FinishTrace** must be used in pairs, and **FinishTrace** matches the latest **StartTrace**. The two APIs can be used in nested mode. The stack data structure is used for matching during trace data parsing. The **limit** parameter is used for flow control, and you are advised to use the default value. + +**Table 2** Async APIs + +| API | Function |Parameter Description | +| ------------------------------------------------------------ | ------------- |------------- | +| void StartAsyncTrace(uint64_t label, const std::string& value, int32_t taskId, float limit = -1); | Starts an asynchronous trace.| **label**: trace category.
**value**: trace data that indicates the specific status, such as the memory size and queue length.
**taskId**: ID used to indicate the association of APIs in an asynchronous trace.| +| void FinishAsyncTrace(uint64_t label, const std::string& value, int32_t taskId); | Stops an asynchronous trace.| **label**: trace category.
**value**: trace data that indicates the specific status, such as the memory size and queue length.
**taskId**: ID used to indicate the association of APIs in an asynchronous trace.| + + + +The trace data of **StartAsyncTrace** and **FinishAsyncTrace** is matched based on **value** and **taskId**, and therefore, the two APIs can be used without a strict sequence. In C++ applications, asynchronous traces are seldom used. + +**Table 3** Counter APIs + +| API | Function |Parameter Description | +| ------------------------------------------------------------ | --------- |--------- | +| void CountTrace(uint64_t label, const std::string& name, int64_t); | Performs a count trace.|**label**: trace category.
**name**: trace name displayed in the IDE.| + + +## How to Develop +1. Add the build dependencies to the build configuration file **base\hiviewdfx\hitrace\cmd\BUILD.gn**. + + ``` + external_deps = [ "hitrace_native:hitrace_meter"] + ``` +2. Add the header file dependencies. + + ```cpp + #include "hitrace_meter.h"// Header file for defining APIs + ``` + +3. When calling an API, pass the trace value as an input parameter. After the hitrace command is executed in the shell, the trace data is automatically captured. The captured data includes the function call process and the memory and time consumed during this process. You can use the data to analyze the call process to identify performance problems. + + + ```cpp + + CountTrace(label, "count number", 2000); // Integer trace + + StartTrace(label, "func1Trace", -1); // Trace start point of func1Start + + FinishTrace(label); // Trace end point of func1Trace + + StartAsyncTrace(label, "asyncTrace1", 1234); // Start point of asyncTrace1 + + FinishAsyncTrace(label, "asyncTrace2", 3456); // End point of asyncTrace2 + ``` + +4. On completion of HiTraceMeter building and deployment, start a trace. After you run the application in the shell on the device, trace data will be captured automatically. + + ``` + hdc_std shell hitrace -t 10 ohos > .\myapp_demo.ftrace + ``` + + You can open the captured data by clicking **Open trace file** in the smartperf tool or dragging the data to the graphics area. For details, see [smartperf](https://toscode.gitee.com/openharmony-sig/smartperf). + +## Development Example + +You can access a full list of trace tags supported by HiTraceMeter in **hitrace_meter.h**. The following uses the **OHOS** tag as an example to illustrate how to obtain the trace data of the **func1** and **func2** functions. + +```cpp +#include "hitrace_meter.h" // Include hitrace_meter.h +using namespace std; + +int main() +{ + uint64_t label = BYTRACE_TAG_OHOS; + sleep(1); + CountTrace(label, "count number", 2000); // Integer trace + + StartTrace(label, "func1Trace", -1); // Trace start point of func1Start + sleep(1); + StartTrace(label, "func2Trace", -1); // Trace start point of func2Start + sleep(2); + FinishTrace (label); // Trace end point of func2Trace + sleep(1); + FinishTrace(label); // Trace end point of func1Trace + + return 0; + } +``` + + + +## Verification + +The following is a demo debugging process, where the **StartTrace** and **FinishTrace** APIs are used in synchronization mode. + +1. Write the test code file [hitrace_example.cpp](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/cmd/example/hitrace_example.cpp) by adding the **StartTrace** and **FinishTrace** APIs to the code. + + ```cpp + int main() + { + thread t1(ThreadFunc1); + t1.join(); + + StartTrace(LABEL, "testStart"); + sleep(SLEEP_ONE_SECOND); + + StartTrace(LABEL, "funcAStart", SLEEP_ONE_SECOND); // Trace start point + FuncA(); + FinishTrace(LABEL); + sleep(SLEEP_TWO_SECOND); + + thread t2(ThreadFunc2); + t2.join(); + + StartTrace(LABEL, "funcBStart", SLEEP_TWO_SECOND); + FuncB(); + FinishTrace(LABEL);// Trace end point + sleep(SLEEP_TWO_SECOND); + + sleep(SLEEP_ONE_SECOND); + FinishTrace(LABEL); + FuncC(); + + return 0; + } + ``` + +2. Modify the **base\hiviewdfx\hitrace\cmd\BUILD.gn** file, and start building. + + ``` + ohos_executable("hitrace_example") { + sources = [ "example/hitrace_example.cpp" ] + + external_deps = [ "hitrace_native:hitrace_meter" ] + + subsystem_name = "hiviewdfx" + part_name = "hitrace_native" + } + + group("hitrace_target") { + deps = [ + ":hitrace", + ":hitrace_example", + ] + } + ``` + +3. Place the **hitrace_example** executable file in the **/system/bin** directory of the device, and run the following commands in sequence in the shell: + + ```shell + hitrace --trace_begin ohos + hitrace_exampe + hitrace --trace_dump + ``` + + If the expected trace value is present in the trace data, the capture of trace data is successful. For example: + + ``` + <...>-1651 (-------) [002] .... 327.194136: tracing_mark_write: S|1650|H:testAsync 111 + <...>-1650 (-------) [001] .... 332.197640: tracing_mark_write: B|1650|H:testStart + <...>-1650 (-------) [001] .... 333.198018: tracing_mark_write: B|1650|H:funcAStart + <...>-1650 (-------) [001] .... 334.198507: tracing_mark_write: E|1650| + <...>-1654 (-------) [003] .... 341.201673: tracing_mark_write: F|1650|H:testAsync 111 + <...>-1650 (-------) [001] .... 341.202168: tracing_mark_write: B|1650|H:funcBStart + <...>-1650 (-------) [001] .... 343.202557: tracing_mark_write: E|1650| + <...>-1650 (-------) [001] .... 346.203178: tracing_mark_write: E|1650| + <...>-1650 (-------) [001] .... 346.203457: tracing_mark_write: C|1650|H:count number 1 + <...>-1650 (-------) [001] .... 347.203818: tracing_mark_write: C|1650|H:count number 2 + <...>-1650 (-------) [001] .... 348.204207: tracing_mark_write: C|1650|H:count number 3 + <...>-1650 (-------) [001] .... 349.204473: tracing_mark_write: C|1650|H:count number 4 + <...>-1650 (-------) [001] .... 350.204851: tracing_mark_write: C|1650|H:count number 5 + <...>-1655 (-------) [001] .... 365.944658: tracing_mark_write: trace_event_clock_sync: realtime_ts=1502021460925 + <...>-1655 (-------) [001] .... 365.944686: tracing_mark_write: trace_event_clock_sync: parent_ts=365.944641 + ``` + + + +# Using the hitrace CLI Tool + +The hitrace CLI tool is an executable binary program. On an OpenHarmony-powered device, you can run the following commands in the shell to capture kernel's running data. + +**Table 4** Command list + +| Option | Description | +| ------------------------------ | ------------------------------------------------------------ | +| -h, --help | Views the help Information. | +| -b *n*, --buffer_size *n* | Sets the buffer size for trace data in KB. The default value is **2048**. | +| -t *n*, --time *n* | Sets the trace uptime in seconds, which depends on the time required for analysis.| +| --trace_clock clock | Sets the type of the clock for adding a timestamp to a trace. The value can be **boot** (default), **global**, **mono**, **uptime**, or **perf**.| +| --trace_begin | Starts capturing trace data. | +| --trace_dump | Dumps trace data to the specified position. The default position is the console. | +| --trace_finish | Stops capturing trace data and dumps trace data to the specified position. The default position is the console. | +| -l, --list_categories | Lists the trace categories supported by the device. | +| --overwrite | Sets the action to take when the buffer is full. If this option is used, the latest trace data is discarded. If this option is not used, the earliest trace data is discarded (default). | +| -o *filename*, --output *filename*| Outputs trace data to the specified file. | +| -z | Compresses the trace data. | + +Examples: + +- Query supported labels. + + ``` + hitrace -l + ``` + + Or, + + ``` + hitrace --list_categories + ``` + + +- Trace ability information for 10 seconds and store the trace data in a buffer of 4 MB. + + ``` + hitrace -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace + ``` + + +- Set the clock type to **mono**. + + ``` + hitrace --trace_clock mono -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace + ``` + + +- Compress the trace data. + + ``` + hitrace -z -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace + ``` + + + +# FAQs + +### Incomplete or Empty Data Captured by hitrace + +#### Symptom + + The data captured by running the hitrace command is incomplete or no data is captured. + +#### Solution + + Check the value of the **-t** and **-b** parameters. If the value is too small, data loss will occur. You are advised to set **-t** to **60** and **-b** to **204800** to increase the trace capture time and buffer, respectively. + + + +# References + +For details about HiTraceMeter, see [hiviewdfx_hitrace: A Lightweight Distributed Tracing](https://gitee.com/openharmony/hiviewdfx_hitrace).