C
Qt Quick Ultralite 性能日志
本主题重点介绍如何获取 Qt Quick Ultralite 应用程序的性能指标和内存占用信息。
Qt Quick Ultralite 性能日志
Qt Quick Ultralite 可以收集重要的性能指标,如下:
- CPU 空闲时间,
- 堆栈和堆的使用情况,
- 帧率,
- 缓存使用情况,
- 渲染上花费时间的有用信息,
- 以及文本布局。
这些日志通过板卡的串行端口输出,可以使用主机上的串行终端观察。要启用和查看性能日志
- 要收集性能指标,Qt Quick Ultralite 核心库必须使用启用
QUL_ENABLE_PERFORMANCE_LOGGING
CMake 选项构建。自 Qt for MCUs 2.6 以来,这是发货库的默认设置。 - 要同时启用性能日志输出到串行控制台,请启用
QUL_ENABLE_PERFORMANCE_CONSOLE_OUTPUT
CMake 选项,并重新构建 Qt Quick Ultralite 核心库。 - 要查看支持它的平台的 CPU 使用情况,必须使用
QUL_ENABLE_HARDWARE_PERFORMANCE_LOGGING
CMake 选项构建 Qt Quick Ultralite 平台库。自 Qt for MCUs 2.6 以来,这是发货库的默认设置。有关更多信息,请参阅 CPU 使用情况。 - 性能日志通过串行连接发送到主机计算机。
- 使用您选择的串行终端查看性能日志输出。
注意:自 Qt for MCUs 2.6 以来,Qt Quick Ultralite Core 和 Platform 库随 QUL_ENABLE_PERFORMANCE_LOGGING
和 QUL_ENABLE_HARDWARE_PERFORMANCE_LOGGING
默认启用发货。虽然这对于分析应用程序很有用,但性能指标收集会给生产就绪的应用程序增加不必要的开销。要移除它,请使用 QUL_ENABLE_PERFORMANCE_LOGGING
和 QUL_ENABLE_HARDWARE_PERFORMANCE_LOGGING
禁用 重新构建 Qt Quick Ultralite 库。
以下步骤将详细介绍。
启用性能日志
要启用 Qt Quick Ultralite 性能日志功能,请使用 -DQUL_ENABLE_PERFORMANCE_LOGGING=on
CMake 选项(在默认启用情况下,Qt for MCU 2.6 已经包括该选项)重新构建 Qt Quick Ultralite Core 库。你可以使用 -DQUL_ENABLE_PERFORMANCE_CONSOLE_OUTPUT=on
CMake 选项与前面的选项一起将日志输出重定向到串行控制台。
如果启用了性能日志,你可以使用 QulPerf QML 类型在 UI 中直接显示指标。
注意:在构建你的应用程序时指定这些选项是不够的。Qt Quick Ultralite 库需要按照 从源代码构建 Qt Quick Ultralite 页面中描述的方式进行构建。
查看性能日志
使用类似于 minicom、gtkterm、PuTTY 或 hyperterm 的串行终端连接到启用了性能日志功能的应用程序运行的设备。
假设设备通过 USB 连接到主设备时使用虚拟 COM 端口提供串行端口,以下是如何查看性能日志的方法。
注意:性能日志只在没有屏幕内容变化时可用。如果没有活动动画,你应该与应用程序进行一些交互,以看到性能日志。
Linux
在 Linux 上,注意目标设备连接到主机器时哪个 /dev/ttyACM*
或 /dev/ttyUSB*
端口出现。如果你使用 minicom,使用以下命令连接到设备
minicom -D /dev/ttyACM2
在某些板子上(如 Infineon TRAVEO™ T2G),可能需要显式地将回车符添加到日志输出中。在 minicom 终端中,你可以通过按 Ctrl+'a' 然后按 'u' 键将回车符添加到传入的文本中。
Windows
以下是如何在 Windows 上使用 PuTTY 终端查看性能日志的步骤。首先,检查设备管理器以查看目标设备连接时出现的哪个设备
相应地配置 PuTTY
- 使用串行连接类型
- 使用设备管理器识别的串行行
- 以及 115200 的速度
你也可以找到目标设备的正确波特率,并相应地调整速度。
此时应该可以看到从 QML 应用程序输出的控制台日志和性能日志。
注意:串行终端方法不适用于 RH850 D1M1A 引用板。相反,使用 MULTI 项目管理器的调试菜单中的“调试其他可执行文件”选项,闪存应用程序 .elf
文件。然后应在调试视图中看到控制台和性能日志。在 RH850 上,日志速度非常慢,所以你应该考虑暂时启用该功能以收集性能指标。
示例日志
以下是在启用 QUL_ENABLE_PERFORMANCE_CONSOLE_OUTPUT
的情况下从性能日志功能产生的示例输出
Memory usage: Heap: 61596/67820 (in-use/total) Stack: 13132 (peak) Resource cache for allocation type 1: 3 texture(s), 1620 KB used / 2160 KB total Text cache: 31481 bytes used out of 32768 bytes max Monotype spark cache: 35056 bytes used out of 200000 bytes max refresh intervals: 1: 7, 2: 18, 3: 6, 10 fps (last 31 frames) animation tick: 0.1% (avg: 0.1 ms, worst: 0 ms) flush: 4.9% (avg: 5.0 ms, worst: 6 ms) repaint: 7.2% (avg: 7.3 ms, worst: 42 ms) prepare: 0.5% (avg: 0.5 ms, worst: 1 ms) region compute: 0.0% (avg: 0.0 ms, worst: 0 ms) paint: 6.5% (avg: 6.6 ms, worst: 41 ms) spark scale change: 0.1% (avg: 0.1 ms, worst: 3 ms) spark glyph retrieval: 0.1% (avg: 0.1 ms, worst: 2 ms) text layout: 0.8% (avg: 0.8 ms, worst: 14 ms) text blend: 0.8% (avg: 0.8 ms, worst: 4 ms) rect blend: 1.8% (avg: 1.8 ms, worst: 9 ms) rect fill: 1.0% (avg: 1.1 ms, worst: 3 ms) image blend: 1.3% (avg: 1.3 ms, worst: 9 ms) alpha w/color: 0.3% (avg: 0.3 ms, worst: 0 ms) alpha: 0.9% (avg: 0.9 ms, worst: 8 ms) opaque: 0.1% (avg: 0.1 ms, worst: 1 ms)
前三行显示应用程序的堆和堆栈使用情况。
然后是当前使用情况和资源(图像)、文本和 Monotype Spark 字体引擎缓存的总量。
接下来是关于需要多少个帧才能在一个、两个或三个刷新(vsync)间隔内渲染的信息。为了一致地以每秒 60 帧的速度渲染,所有帧必须在一个刷新间隔内渲染完成。
“10 fps”行(最后 31 帧)表示这些统计信息是针对上一个 31 帧,平均每秒 10 帧。
最后,这里有 Qt Quick Ultralite 渲染管道各部分的计时统计。平均 (avg) 值表示某些帧的平均耗时,而最坏 (worst) 值表示单个帧的最大耗时。以下是在日志中可能会看到的不同计时统计概述:
入口 | 描述 |
---|---|
动画计时器 | 在 QML 动画中推进所有 QML 动画所花费的时间,例如 NumberAnimation。 |
刷新 | 在 Qul::Platform::PlatformContext 的成员函数 beginFrame() 和 presentFrame() 上花费的时间。它主要指示等待垂直刷新的时间。在这里花费大量时间并不表示应用程序性能不好,而是意味着有很多空闲时间,没有用来准备或渲染帧。 |
重绘 | 动画中变化的区域准备和绘制所花费的时间。 |
准备 | 准备 QML 项渲染节点所花费的时间。这包括标识当前可见的 QML 项的边界矩形。 |
区域计算 | 基于可见项的边界矩形为每帧计算脏区域的耗时。 |
不透明度计算 | 计算不透明区域以尽可能减少过度绘制所花费的时间。 |
绘制 | 绘制所有可见项的总耗时。 |
Spark 放大缩放变化 | 在 Monotype Spark 字体引擎中为像素大小变化做准备所花费的时间。 |
Spark 字形检索 | 在 Monotype Spark 字体引擎中光栅化字形,然后将其保留在字体引擎缓存中。 |
CPU 访问同步 | 使用后备绘图引擎时,同步 CPU 访问所花费的时间。 |
文本布局 | 布局文本所花费的时间,然后将文本直接绘制到帧缓冲区或文本缓存中。 |
文本混合 | 对文本混合所花费的时间,要么是逐个字形地混合,要么是使用文本缓存进行混合。 |
矩形混合 | 混合半透明矩形(矩形 QML 类型)所花费的时间。 |
矩形填充 | 填充不透明矩形(矩形 QML 类型)所花费的时间。 |
矩形圆角 | 混合圆角矩形(带有半径设置的矩形 QML 类型)所花费的时间。 |
图像变换 | 混合变换后的(缩放、旋转、倾斜和投影)图像的总耗时。 |
图像混合 | 混合非变换图像的总耗时。 |
alpha w/颜色 | 混合使用 PixelFormat_Alpha8 格式以及颜色(例如使用 ColorizedImage)的图像所花费的时间。 |
alpha | 混合具有 alpha 通道(PixelFormat_ARGB32、PixelFormat_ARGB4444 等)的图像所花费的时间。 |
不透明 | 混合具有 alpha 通道(PixelFormat_ARGB32、PixelFormat_ARGB4444 等)的图像所花费的时间。 |
路径混合 | 混合来自 QML Shape API 或使用矢量轮廓的文本所花费的时间。 |
CPU 使用率
要查看支持该功能的平台的 Qt Quick Ultralite CPU 使用率,请使用具有 -DQUL_ENABLE_HARDWARE_PERFORMANCE_LOGGING=on
CMake 选项重新构建 Qt Quick Ultralite 平台库。
CPU 负载信息如下所示
CPU Load: 44.47
此示例表示 CPU 负载为 44.47 %。CPU 大约有一半的时间是空闲的。
注意:在支持此功能的参考平台上,CPU 使用率是根据 CPU 空闲时间估计的。
内存占用
当确定应用程序需要多少RAM和闪存,或在尝试减小二进制文件大小时,足迹信息非常重要。您可以使用受支持的工具链和资源缓存应用程序提供的工具来获取Qt Quick Ultralite应用程序的足迹信息。
工具
工具链特定的工具可以用来确定应用程序二进制的内存消耗。这些工具具有不同的标志并产生不同的输出。以下小节列出了Qt为MCU支持的三种工具链提供的工具:ARM GCC、IAR和GHS。
ARM GCC
ARM GCC包括两个单独的工具,可用于确定应用程序的内存消耗:size
和readelf
。这些工具可以在ARM GCC安装目录下的bin
目录中找到。二进制文件以arm-none-eabi-
为前缀,例如size
二进制文件命名为arm-none-eabi-size
。它们也包含在
size
是一个实用程序,它列出了二进制或存档的节的大小。节的大小可以以各种格式显示
- SystemV格式(《a class="plink" href="#systemv" title="直接链接到此标题">或
-A
或--format=sysv
)这种格式显示所有节及其大小列表。建议使用SystemV格式来获取二进制文件中包含的节及其大小和地址的良好概述。 - Berkeley格式(
-B
或《a class="plink" href="#berkeley" title="直接链接到此标题">或--format=berkeley
)GNU size的默认格式。Berkeley格式在text
列中计算只读数据,而不是在data
列中,dec
和hex
列分别以十进制和十六进制形式显示text
、data
和bss
列的总和。 - GNU格式(
-G
或--format=gnu
)GNU格式在data
列中计算只读数据,而不是在text
列中,并将text
、data
和bss
列的总和在total
列中只显示一次。可以使用--radix
选项来更改所有列的数值基。
readelf
是一个用于显示关于ELF格式对象文件信息的工具。它可以从二进制文件中收集广泛的多种信息,例如节的大小、程序头部和符号。要测量应用程序的足迹,请使用标志-S
、--section-headers
或--sections
以获取有关所有节、它们的大小和其他有用信息。
此外,可以使用编译器标志-Wl,--print-memory-usage
。然后链接器将打印出链接器脚本中配置的所有内存区域、它们的实际大小以及以字节数和百分比表示的使用大小。
注:使用-Wl,--print-memory-usage
不会显示节的大小,因此不能用于显示例如QulResourceData
节的大小。
IAR
IAR工具链提供ielfdumparm
,该工具用于创建ELF文件内容的文本表示。它位于IAR安装目录的arm/bin
中。要获取有关二进制文件中包含的扇区和段的信息,请运行ielfdumparm <input>
。
获取有关不同节的信息的另一种方法是使用链接器中的--map
标志。这将生成一个链接器内存映射文件,其中包含有关节及其在内存中位置的详细信息。
注意:该 qul_add_target
Qt Quick Ultralite CMake 宏会自动将 --map
添加到目标链接器选项中。生成的内存映射可以在与目标二进制相同的目录中找到。映射文件的名称为 <target>.map
。
有关 ielfdumparm
或使用 --map
链接器选项的更多信息,请参阅 IAR C/C++ 开发指南
。
GHS
GHS 工具链具有用于测量段大小的 gsize
实用工具。它位于 GHS 编译器安装目录下。gsize
分析二进制文件并输出段及其大小。如果提供 -all
标志,它还会列出所有大小为 0 的段。
GHS 链接器 elxr
提供了 -map
选项,可以将单独的 <target>.map
文件输出到生成目标二进制文件的同一位置。此文件包含有关目标二进制文件的大量信息,包括包含在二进制文件中的段及其大小。此链接器选项默认启用,但可以通过指定 -map=<filename>
甚至 -nomap
来更改。这些选项允许更改映射文件的输出位置或彻底禁用映射文件生成。
有关 gsize
或使用 -map
链接器选项的更多信息,请参阅 MULTI: 构建基于 ARM 的嵌入式应用程序
(或根据目标架构相似的内容)文档。
闪存使用情况
默认情况下,Qt Quick Ultralite 在闪存中有三个资源段。这些段分别用于存储字体资产、图像资产和 Qt Quick Ultralite 内部资源,名称为 QulFontResourceData
、QulResourceData
和 QulModuleResourceData
。有关这些段的信息,请参阅内存中的资源放置和链接器脚本设置。
要获得这些段的大小,请使用工具部分中提到的工具。这些工具的输出应类似于 size -A minimal.elf
的输出。
section size addr .flash_config 512 805307392 .ivt 1336 805310464 .interrupts 1024 805314560 .text 347552 805315584 CodeQuickAccess 56 805663136 .ARM 8 805663192 .init_array 8 805663200 .fini_array 8 805663208 .data 236 2147483648 .ncache.init 0 2197815296 .ncache 2097152 2197815296 .bss 13104 2147483888 QulFontResourceData 21736 805663456 QulModuleResourceData 0 2147496992 QulResourceData 0 805685192 QulPreprocessCache 524288 2147496992 .heap 0 2148021280 .ARM.attributes 46 0 .debug_info 5402684 0 .debug_abbrev 253660 0 .debug_loc 871154 0 .debug_aranges 12520 0 .debug_ranges 100040 0 .debug_line 908143 0 .debug_str 3705172 0 .comment 73 0 .debug_frame 51112 0 .debug_macro 570227 0 .stab 60 0 .stabstr 118 0 Total 14882029
注意:段名称可能取决于使用的链接器脚本。
估计 RAM 使用量
Qt Quick Ultralite 应用程序需要以下 RAM:
- 帧缓冲区
- 栈
- 堆
- 缓存(用于文本、字体引擎和图像)
- 资源
- Qul 项数据
以下部分将解释如何估算或收集这些项目的内存占用信息。
帧缓冲区
矩形屏幕的帧缓冲区大小可以用以下公式估算
Framebuffer size in bytes = width x height x bytes per pixel x number of buffers
其中
width
是屏幕的宽度(像素)height
是屏幕的高度(像素)- 每像素的字节数是每个像素使用的字节数。如果已知比特深度,可以将比特深度除以 8 来计算每像素的字节数。对于 32bpp 帧缓冲区,每像素的字节数是
32 / 8 = 4
。 number of buffers
取决于使用的缓冲区策略。对于单缓冲区,该值应为 1,对于双缓冲区,该值应为 2。
如果用于屏幕的帧缓冲区不是矩形的,则此大小估算可能会有所不同。在这种情况下,可以将先前的公式中的 width x height
替换为帧缓冲区中的总像素数。
有关帧缓冲区及其要求的更多信息,请参阅 帧缓冲区要求。
堆栈和堆
Qt Quick Ultralite(平台)提供了两个打印堆栈和堆统计信息的功能:Qul::Platform::printStackStats 和 Qul::Platform::printHeapStats。要使用这些函数,它们必须在平台代码中实现。有关如何实现这些函数的更多信息,请参阅 内存统计信息。
资源缓存
典型的 Qt Quick Ultralite 应用程序可以有以下几种类型的缓存
为了在内存使用和性能之间取得最佳平衡,调整这些缓存的大小可能很重要。以下是估算它们适当大小的指南,以适应您的应用程序
文本缓存
对于文本缓存,理想的大小取决于屏幕上文本的多少以及文本的像素大小。例如,在 Qt Quick Ultralite 最小示例 中,像素大小为 30 的 "Qt for MCUs" 文本消耗了 6899 字节。绘制文本项所需的字形边界框宽度为 183 像素,高度为 37 像素。
由于您需要一个字节来表示每个像素的透明度,因此它的alpha图所需字节数可以计算如下
183 x 37 = 6771 字节
此外,每个缓存条目还包括一小部分元数据,这就是为什么最终所需数量略高的原因。
为了理想性能,单页应用程序至少应该有一个足够大的文本缓存,可以容纳该页上的所有文本。如果页面的10%被文本覆盖,并且屏幕分辨率为800x480,则需要38.4 Kb的文本缓存。
如果有两个或更多页面,并且存在它们之间的淡入淡出过渡动画,则理想的文本缓存大小应该能够容纳两个页面上的文本。
可以使用较小的文本缓存来牺牲一些性能以换取较低的内存使用,但这可能意味着在动画或过渡期间需要重新生成某些文本缓存条目。使用 Monotype Spark 字体引擎时,生成文本缓存条目的成本将高于使用静态字体引擎,因此如果在性能问题上特别重要,则可能需要保持文本缓存大小足够。
另外要注意的是,如果销毁了文本项并重新创建了它们,相关的文本缓存条目也将随时自动重新生成,一旦文本项可见。更改文本或任何其他影响其外观的属性,也将使文本缓存条目无效。
请参阅有关文本缓存大小的更多信息文本渲染和字体页面。
可以通过查看Qt Quick Ultralite 性能日志来查看应用程序使用的文本缓存大小。
字体引擎缓存
Monotype Spark 字体引擎使用字体引擎缓存存储每个光栅化的字形的alpha图。如果缓存足够大,则字形只绘制一次,而不是每次绘制(无论是文本缓存还是禁用文本缓存时绘制到帧缓冲区)。
例如,在 Qt Quick Ultralite Thermostat 示例 中,至少需要50 Kb的字体引擎缓存才能在一个 800x480
分辨率下保持单一语言的全部alpha图。
拥有足够大的文本缓存时,字体引擎缓存将在首次显示文本项或文本变更时被访问。然而,当动画运行时,文本缓存可能在每一渲染帧中被访问。因此,为了性能考虑,通常较好的做法是为文本缓存分配比字体引擎缓存更多的内存。另一方面,由于字形缓存是按字形进行的,同一个字形可能在不同文本项中出现多次,所以字体引擎缓存更节内存。
如果启用了MCU.Config.fontVectorOutlinesDrawing,则字体引擎缓存仅用于CMAP和Advance缓存,而不用于矢量轮廓。因此,它可以保持相对较小,而文本缓存应保持较大,以避免重新生成矢量轮廓。
有关字体引擎缓存大小的更多信息,请参阅文本渲染和字体页面。
应用程序使用的字体引擎缓存大小可以通过查看Qt Quick Ultralite性能日志来查看。
图像缓存
图像缓存应足够大,以便能够容纳屏幕上同时可见的所有图像(使用OnDemand
缓存策略)。否则,大图像可能在一帧中被反复载入和卸载到RAM中,显著影响性能。特别是如果启用了ImageFiles.MCU.resourceCompression,它会在将图像加载到图像缓存之前添加额外的解压缩开销。
例如,一个在两页之间切换的应用程序,一页包含两个200x200的图像,另一页包含一个320x200的图像。如果图像的颜色深度为每像素32位(4字节),那么理想图像缓存大小的计算如下
缓存大小(带过渡)= 2 x 200 x 200 x 4 + 320 x 200 x 4
= 576000字节
这确保了两页之间的过渡动画平滑。如果没有过渡动画,可以使用尺寸要求最大的页面
缓存大小(不带过渡)= 2 x 200 x 200 x 4
= 320000字节
有关图像缓存大小的更多信息,请参阅图像缓存页面。
应用程序使用的图像缓存大小可以通过查看Qt Quick Ultralite性能日志来查看。
预加载资源占用的RAM
预加载资源占用的RAM量取决于你在项目中如何配置资源预加载。默认情况下,所有图像、字体和Qt Quick Ultralite项数据资源都在应用程序启动时预加载到RAM中。使用此选项,预加载资源的RAM使用量可能会很高,对于所有Qt Quick Ultralite资源部分的总和(没有ImageFiles.MCU.resourceCompression)。有关如何获得Qt Quick Ultralite资源部分的大小,请参阅闪存使用情况。
可以通过设置 QmlProject 属性来控制行为 ImageFiles.MCU.resourceCachePolicy。如果定义在 ImageFiles
中,也可以为单个资源设置,如果定义在 MCU.Config
中,则可以设置所有资源的预加载。有关 ImageFiles.MCU.resourceCachePolicy
以及变量取可能值得信息,请参阅 ImageFiles.MCU.resourceCachePolicy
。
在特定 Qt 许可证下提供。
了解更多。