diff --git a/zh-cn/application-dev/reference/native-lib/libuv.md b/zh-cn/application-dev/reference/native-lib/libuv.md index 65c7e509a49df3ce901b9033385ac4ddc93dc466..0c4cbeaf203044b23481673f7961f3d1ef476e4a 100644 --- a/zh-cn/application-dev/reference/native-lib/libuv.md +++ b/zh-cn/application-dev/reference/native-lib/libuv.md @@ -1558,6 +1558,72 @@ int uv_getnameinfo(uv_loop_t* loop, - signal相关函数 - tcp及udp相关函数 +### 功耗相关 + +在OpenHarmony系统中,ArkTS侧提供的定时器接口分别为`setInterval`和`setTimeout`,这两个接口的底层实现都使用了libuv提供的定时器能力。在native侧则可以调用libuv的timer接口`uv_timer_start`来创建定时器任务。对libuv timer接口的直接或间接不当调用,可能会导致高功耗问题,接下来介绍两种使用timer接口不当导致的潜在高功耗问题。 + +1、 传入参数不当 + +开发者可以访问[定时器](../../reference/common/js-apis-timer.md)查看定时器的详细介绍。`setinterval`的接口描述如下: +```typescript +/** +* @brief 用于创建一个定时器,该定时器重复调用一个函数,在每次调用之间具有固定的时间延迟。 +* +* @param handler 定时器到期后执行的函数,若为string,则打印string中内容,不进行其他处理 +* @param delay 延迟的毫秒数,函数调用会在该延迟之后发生 +* @param rest 附加参数,仅当handler的类型为Function时生效,作为参数传递给handler +* +* @return number 定时器id,无重复值 +**/ +setInterval(handler : Function | string, delay : number, ...arguments: any []) : number +``` + +另一个定时器接口是`setTimeout`,其接口描述如下: +```typescript +/** +* @brief 用于创建一个定时器,该定时器在回调被执行后自动删除,或者调用clearTimeout接口手动删除。 +* +* @param handler 定时器到期后执行的函数,若为string,则打印string中内容,不进行其他处理 +* @param delay 延迟的毫秒数,函数调用会在该延迟之后发生 +* @param rest 附加参数,仅当handler的类型为Function时生效,作为参数传递给handler +* +* @return number 定时器id,无重复值 +**/ +setTimeout(handler: Function | string, delay?:number, ...arguments:any[]) : number +``` + +**需要注意的是,在原生Javascript中,调用setInterval时允许传入的delay值小于0,在OpenHarmony中也未作约束,但是这可能会引发功耗问题。应用在arkTS主线程调setInterval接口时,如果delay小于0,底层会在提交定时器任务的时候,将该值强制设置为1,即以1ms的间隔执行定时器任务,会导致系统频繁调度定时器回调,从而导致功耗增加**。因此开发者使用该接口时,需检查一下传入的delay值是否为通过计算得到的,如果是,**请增加异常检查,当delay小于0时,将其设置成合适的值**。 +此外,当delay参数被开发者省略,或者小于1,或者超出2^32 - 1时, delay会被设置为默认值0,这可能会导致定时器回调被高频调用,从而引发功耗问题。 + +libuv创建定时器的接口描述如下: + +```c +/** +* @brief 用于创建一个定时器,该定时器重复调用一个函数,在每次调用之间具有固定的时间延迟。 +* +* @param handle 定时器句柄,用来表示一个定时器任务 +* @param cb 定时器回调,当定时器任务超时时执行 +* @param timeout 从创建定时器任务开始到执行定时器任务的间隔时间 +* @param repeat 定时器重复执行的时间间隔 +* +* @return int 状态值,成功时返回1,失败时返回-22 +**/ +int uv_timer_start(uv_timer_t* handle, + uv_timer_cb cb, + uint64_t timeout, + uint64_t repeat) +``` + +同理,在native侧调`uv_timer_start`创建定时器任务时,如果将repeat值设置的过小,可能会导致功耗问题。 + +2、 误用定时器接口 + +开发者应当明确`setInterval`接口和`setTimeout`接口的区别,当接口使用不当时,可能会导致发生功耗问题。前者是提交一个重复的定时器任务,每隔一段时间执行一次定时器任务,直到手动删除该定时器;而后者是提交一个一次性的定时器任务,即该定时器任务任务只会在超时时执行一次,随后自动删除。 + +比如原意是要提交一个单次执行的定时器任务,下一次再新创建一个,此时应该调用`setTimeout`接口,结果错误地调用了`setInterval`接口,将其提交成可重复执行的定时器任务,并且没有手动清除该定时器,**随着接口错误调用的次数越来越多,就会导致积累在系统中的定时器任务越来越多,从而导致功耗问题**。 + +此外,开发者大量往主线程的loop上提交定时器任务,或者提交的定时器任务很耗时,**除了造成功耗问题外,还可能会导致主线程无法响应watchdog任务或者输入事件,从而发生freeze问题**。 + ## 技术案例 [libuv中主线程timer回调事件触发时间不正确原因](https://gitee.com/openharmony/third_party_libuv/wikis/06-Wiki-%E6%8A%80%E6%9C%AF%E8%B5%84%E6%BA%90/libuv%E4%B8%AD%E4%B8%BB%E7%BA%BF%E7%A8%8Btimer%E5%9B%9E%E8%B0%83%E4%BA%8B%E4%BB%B6%E8%A7%A6%E5%8F%91%E6%97%B6%E9%97%B4%E4%B8%8D%E6%AD%A3%E7%A1%AE%E5%8E%9F%E5%9B%A0)