黑暗模式
9. AWTK 资源占用
程序的 ROM 和 RAM 资源占用一直都是嵌入式开发关心的问题,ROM 上通常存放代码、常量和应用资源数据,RAM 内存通常存放 Framebuffer、AWTK 框架功能以及应用程序的动态内存。应用相关的资源占用与应用的规模强烈相关,而 Framebuffer 则与平台的缓冲数量、屏幕分辨率以及颜色深度等相关,用户可以自行估算出来。本章仅讨论 AWTK 框架功能的资源占用(AWTK 核心和非核心模块代码 ROM 以及 RAM 的占用情况)。
9.1 资源占用
AWTK 中有核心代码和非核心代码,核心代码就是不能裁剪,必须要添加到项目中的代码,而非核心代码又分为控件和可裁剪的功能模块,所以 AWTK 资源占用可以简单分为三部分:无法裁剪的核心功能模块,可裁剪的功能模块以及控件。本章节讨论是这三部分的资源占用情况。
测试说明:
- 本章节的内存占用测试是在 32 位的 MCU 上进行的,在 64 位的 MCU 上测试结果可能会不一样。
- 本章节的 ROM 占用测试是在无调试信息以及编译选项为 -Os 的情况下进行的,数据通过 arm-none-eabi-size.exe 测试得到。
9.1.1 核心功能模块的资源占用
将 AWTK 的非核心代码全部裁剪掉,核心代码的 ROM 占用约为 100KB,RAM 占用约为 3KB,AWTK 核心模块介绍及其内存占用请参考本文附录三。
需要注意的是:
- 由于 AWTK 存在图片缓冲机制,显示全新图片时,如果内存足够,图片管理器的内存都会增加。
- 不同的 lcd_t 类型内存占用都不一样,lcd_t 对象一般仅占几百个字节,真正占用内存的是 Framebuffer。
- 要注册 UI 控件还需要加上额外的 3KB 控件管理器内存。
在内存资源紧缺的平台上,用户可以在适当时机(比如切换窗口时),手动调用 image_manager_unload_unused 或者 image_manager_unload_all 函数来及时清除图片缓存,避免图片缓冲机制与其他业务逻辑抢资源。
9.1.2 可裁剪的功能模块的资源占用
功能模块 | 宏 | ROM 占用 | RAM 占用 |
---|---|---|---|
图片解码模块 | WITH_STB_IMAGE | 约 35.9KB | PNG:解码瞬时峰值内存占用约为两份位图数据。 JPG:18KB + 解码瞬时峰值内存占用约为三份位图数据。 GIF:解码后大约为所有帧的位图数据总和 |
字体解码模块 | WITH_STB_FONT | 约 15.1KB | stb 字库对象为:3.2KB + 用到的字模缓存数据 |
标准的 UNICODE 换行算法模块 | WITH_UNICODE_BREAK | 约 47.3KB | 大于1.39KB |
Google 拼音输入法功能 | WITHOUT_INPUT_METHOD、 WITH_NULL_IM | 约 24.5KB + 1.1MB(输入法资源) | 大于700KB |
AGGE 矢量画布模块 | WITH_NANOVG_AGGE | 约 10KB | 大于 30KB(18.8KB + 缓存数据) |
窗口动画功能 | WITHOUT_WINDOW_ANIMATORS | 约 3.3KB | 520B + 两份显存大小的瞬时峰值 |
布局算法模块 | WITHOUT_LAYOUT | 大约 1.9KB | 128B |
控件动画功能 | WITHOUT_WIDGET_ANIMATORS | 大约 3KB | 120B |
剪切板模块 | WITHOUT_CLIPBOARD | 大约 232B | 16B |
对话框高亮策略模块 | WITHOUT_DIALOG_HIGHLIGHTER | 大约 1.2KB | 60B |
加载文件系统资源模块 | WITH_FS_RES | 大约 5.5KB | 0B |
扩展控件 | WITHOUT_EXT_WIDGETS | 大约 90KB | 0B |
基本控件 | AWTK_NOGUI | 大约 12.3KB | 0B |
需要注意的是:
- WITH_ 开头的宏用于开启某个功能模块,WITHOUT_ 开头的宏用于裁剪某个功能模块,通常 AWTK 默认开启的功能,需要用 WITHOUT_ 开头的宏来裁剪,默认不开启的功能,需要用 WITH_ 开头的宏来开启。
- 图片解码器最大的问题是解码时,峰值内存较高,尤其是在解码 JPG 时,如果 JPG 类型为 YUV ,峰值会根据 YUV 的采样比来决定,上表中默认采样比为 1,如果采样比大于 1,峰值内存只会更大。
- JPG 和 PNG 解码完成后,会释放解码时开辟的多余的峰值内存,将一份解码后的位图的数据存放到 AWTK 的图片缓冲中。
- GIF 格式的解码仅在开启图片解码模块以及通用文件系统模块时支持,并且解码后的 GIF 所有帧都会被拼接到一张 bitmap 中,所以 GIF 的内存占用为所有帧的位图数据总和。
- Truetype 字体解码器本身不占什么内存,但由于缓存机制,字模的内存占用会随着显示字符的增多而变大,每个字模内存约等于字号*字号所占字节。
- Nanovg 和 Agge 是 AWTK 自带的第三方的矢量画布类库。
- 在矢量画布中,缓存数据分别在 nanovg 和 AGGE 中,nanovg 创建的时候默认包含了 128 个 point(约 32B),16 个 path(约 40B)和 256 个 vertex(约 16B),但如果运行过程中同一帧内的缓存数据超过默认的缓存数量,就会重新分配缓冲数据,这会增加矢量画布的内存占用量。
- AGGE 创建时没有默认缓存数据,它绘制前会把 nanovg 的缓存数据转为坐标点(约 12B),如果当前的坐标点个数超过之前缓存的坐标点个数,就会重新分配缓存坐标点数组,同时如果让 AGGE 画一个全新的图片,就会增加一个贴图缓存(约 32B),所以 AGGE 运行时会增加矢量画布的内存占用量。
9.1.3 控件的资源占用
关于控件的资源占用:
除了控件自身的最低运行内存占用以外,修改控件相关属性以及设置 inline_style(在 UI 文件中增加的风格属性就是 inline_style),都可能导致控件的内存变大,同时每创建一个控件就会多占用一份内存,每个控件的内存都是独立的。
控件占用的 ROM 计算比较简单,每种控件的 ROM 占用都是固定的,而且还有一些控件是公用同一个代码文件的,所以多个控件占用同一份 ROM。
下面列出一些常用的控件资源占用列表,在附录四中会列出所有 AWTK 的控件资源占用列表。
控件名称 | ROM 占用 | 最少 RAM 占用 |
---|---|---|
dialog | 大约 1.2KB | 424B |
window | 567B | 412B |
image | 大约 1KB | 168B |
button | 大约 1.7B | 160B |
label | 大约 3.3KB | 148B |
progress_bar | 大约 2.5KB | 160B |
check_button | 大约 1.6KB | 140B |
radio_button | 大约 1.6KB | 140B |
system_bar | 983B | 444B |
system_bar_bottom | 983B | 444B |
view | 509B | 140B |
edit | 大约 19.5KB | 868B |
combo_box | 大约 5.5KB | 大约 1.2KB |
combo_box_item | 大约 1.3KB | 144B |
scroll_view | 大约 6.6KB | 272B |
list_view | 大约 3KB | 160B |
list_item | 大约 1KB | 152B |
scroll_bar | 大约 5.8KB | 164B |
scroll_bar_d | 大约 5.8KB | 920B |
scroll_bar_m | 大约 5.8KB | 164B |
combo_box_ex | 601B | 大约 1.4KB |
9.2 评估项目资源占用方法
9.2.1 评估项目 AWTK 相关 ROM 的大小
只保留 AWTK 的核心代码和基础控件时 ROM 约为 130KB,根据实际需求再加上使用的控件和功能模块的 ROM 大小。如果没有定义 WITHOUT_EXT_WIDGETS 和 AWTK_NOGUI 宏,那么控件占用的 ROM 分别为 90KB 和 12.3KB,不论用到多少个控件,都占用相同的 ROM。
9.2.2 评估项目 AWTK 相关 RAM 内存大小
假设 LCD 是 800 * 480 的 16 位色屏幕,采用双 Framebuffer 机制,计算内存的步骤如下:
双 Framebuffer 的显存为:800 * 480 * 2 * 2 = 1.5MB。
估算 AWTK 使用的总 Heap 大小:
(1) 计算 Heap 中的小对象内存池大小,详见附录三。
(2) 统计要使用的可裁剪的功能模块,计算所用到的模块的内存总和。
(3) 统计要使用的控件,以及同一画面中有多少个控件,计算所有显示的控件的内存占用总和。
(4) 如果开启了图片解码模块,则需要计算解码峰值,以及同一个画面显示的所有贴图缓存的内存总和。
(5) 如果开启了字库解码模块,则需要计算同一个画面显示的所有字符缓存的内存总和。
(6) 如果开启窗口动画模块,则需要分配额外两份 Framebuffer 大小的内存,用于保存前后两个窗口的截图。
(7) 程序运行过程中可能会出现内存碎片,汇总好以上内存占用量之后,再乘以系数 1.2 到 2,就可以得出来项目大概需要多少内存。
9.2.3 评估项目其他资源占用
不同领域的项目应用程序规模差异较大,用户需要自行估算其他业务逻辑的 ROM 和 RAM 占用,以及用到的图片字体等资源数据的 ROM 占用情况。
在项目资源中,通常占 ROM 最多的通常是图片资源和字体资源,其中字体资源可以通过 AWTK Designer 的资源管理器进行裁剪。
9.3 平台资源和功能模块裁剪建议
9.3.1 ROM 和功能模块
该表中仅代表 AWTK 本身占用的 ROM,不包括应用程序自己的的代码以及资源数据。
平台 | ROM 大小 | 建议裁剪(禁用)的 AWTK 功能 |
---|---|---|
高资源平台 | (2MB, +∞ ] | 无 |
中资源平台 | (256KB,2MB] | 拼音输入法功能(包括输入法资源,约占 1.1MB ROM) |
低资源平台 | (128KB,256KB] | 除位图字体功能,位图贴图功能以及部分基本控件之外的所有功能 |
9.3.2 内存和功能模块
该表中仅代表 AWTK 本身占用的运行内存,不包括显存和应用程序所需的其他业务内存。内存比较小的情况下尽量使用相同字号和相同字库的字符。
平台 | RAM 大小 | 建议裁剪(禁用)的 AWTK 功能 |
---|---|---|
高资源平台 | (4MB, +∞ ] | 无 |
中资源平台 | (2MB,4MB] | 拼音输入法功能(包括输入法资源) |
中资源平台 | (1MB,2MB] | 播放窗口动画模块,对话框高亮策略模块,图片解码功能 |
低资源平台 | (512KB,1MB] | 布局算法模块,Truetype 字库解码模块, AGGE 矢量画布模块 |
低资源平台 | (128KB,512KB] | 标准的 UNICODE 换行算法, 剪切板算法,加载文件系统资源模块 |
低资源平台 | (10KB,128KB] | 除位图字体功能,位图贴图功能以及部分基本控件之外的所有功能 |