掌桥专利:专业的专利平台
掌桥专利
首页

任务处理方法、介质、装置和计算设备

文献发布时间:2023-06-19 19:30:30


任务处理方法、介质、装置和计算设备

技术领域

本公开的实施方式涉及计算机领域,更具体地,本公开的实施方式涉及任务处理方法、介质、装置和计算设备。

背景技术

本部分旨在为权利要求书中陈述的本公开的实施方式提供背景或上下文。此处的描述不因为包括在本部分中就承认是现有技术。

在安卓(Android)操作系统中,通常会有一些耗时的任务(简称“耗时任务”)需要执行,这些耗时任务一般放在子线程中处理,以避免出现用户界面(User Interface,简称UI)线程卡顿的情况。但是不可避免的,依然会存在必须要在UI线程中执行的耗时任务,从而导致UI线程执行耗时任务而出现卡顿的情况。

相关技术中,为了解决UI线程执行耗时任务而出现卡顿的问题,当UI线程处理完当前时间点的UI渲染任务和用户自定义的耗时任务等耗时任务之后,会执行Android系统提供的任务调度器,以对任务调度器调度的其他耗时任务进行执行。但依然会存在UI线程的卡顿或者跳帧的问题。

发明内容

本公开提供一种任务处理方法,可以避免UI线程的卡顿或者跳帧。

在本公开实施方式的第一方面中,提供了一种任务处理方法,包括:确定当前帧的空闲时间切片,空闲时间切片的起始时刻为用户界面UI线程开始空闲的时刻,空闲时间切片的结束时刻为当前帧的结束时刻;获取任务处理时长小于或等于空闲时间切片的目标任务;在空闲时间切片内,执行目标任务。

在本公开的一个实施例中,获取任务处理时长小于或等于空闲时间切片的目标任务,包括:获取任务列表,任务列表中包括至少一个任务队列,每个任务队列中包含的待处理任务的任务处理时长相同,不同任务队列中包含的待处理任务的任务处理时长不同;在任务列表中确定第一任务队列,第一任务队列对应的任务处理时长小于或等于空闲时间切片;在第一任务队列中确定目标任务。

在本公开的另一实施例中,获取任务列表之前,还包括:采用链表结构构建任务列表中的至少一个任务队列;获取待处理任务;将获取到的待处理任务添加至任务列表中的第二任务队列,得到任务列表,第二任务队列对应的任务处理时长与获取到的待处理任务的任务处理时长相同。

在本公开的又一个实施例中,将获取到的待处理任务添加至任务列表中的第二任务队列,包括:响应于获取到的待处理任务的任务处理时长小于或等于预设值,将获取到的待处理任务添加至第二任务队列,第二任务队列的数量为一个;响应于获取到的待处理任务的任务处理时长大于预设值,对获取到的待处理任务进行拆分处理,得到多个子任务;按照子任务的任务处理时长,将多个子任务添加至第二任务队列,第二任务队列的数量为多个。

在本公开的再一个实施例中,还包括:确定获取到的待处理任务在预设时间范围内的历史任务处理时长;将历史任务处理时长中的最大值,确定为获取到的待处理任务的任务处理时长。

在本公开的再一个实施例中,将获取到的待处理任务添加至任务列表中的第二任务队列之前,还包括:将待处理任务与当前帧所在的页面的生命周期进行绑定处理。

在本公开的再一个实施例中,在空闲时间切片内,执行目标任务之后,还包括:确定并存储目标任务在空闲时间切片内的执行时长;根据执行时长,更新空闲时间切片。

在本公开的再一个实施例中,任务列表中的至少一个任务队列按照对应的任务处理时长从小到大的顺序排列;任务处理方法还包括:响应于监测到用于表示任务调度超时的标志信息,将任务列表中的第一个非空任务队列确定为第三任务队列;获取第三任务队列中的第一个任务进行执行。

在本公开的再一个实施例中,还包括:在任务执行完成之后,在对应的任务队列中删除执行完成的任务。

在本公开的再一个实施例中,确定当前帧的空闲时间切片,包括:获取当前帧的渲染任务的开始时刻和结束时刻;根据开始时刻和结束时刻,确定渲染任务的渲染时长;将当前帧的刷新时长和渲染时长的差值,确定为空闲时间切片,刷新时长通过用户界面的刷新频率确定,刷新时长大于或等于渲染时长。

在本公开的再一个实施例中,获取当前帧的渲染开始时刻和渲染结束时刻,包括:调用当前帧的第一监听回调函数,确定渲染开始时刻,第一监听回调函数用于监听渲染任务的开始时刻;调用当前帧的第二监听回调函数,确定渲染结束时刻,第二监听回调函数用于监听渲染任务的结束时刻。

在本公开实施方式的第二方面中,提供了一种介质,介质中存储有计算机执行指令,计算机执行指令被处理器执行时用于实现如第一方面的任务处理方法。

在本公开实施方式的第三方面中,提供了一种任务处理装置,包括:确定模块,用于确定当前帧的空闲时间切片,空闲时间切片的起始时刻为用户界面UI线程开始空闲的时刻,空闲时间切片的结束时刻为当前帧的结束时刻;获取模块,用于获取任务处理时长小于或等于空闲时间切片的目标任务;执行模块,用于在空闲时间切片内,执行目标任务。

在本公开实施方式的第四方面中,提供了一种计算设备,包括:处理器,以及与处理器连接的存储器;存储器存储计算机执行指令;处理器执行存储器存储的计算机执行指令,以实现如第一方面的任务处理方法。

根据本公开实施方式的任务处理方法,通过确定UI线程每一帧的空闲时间切片,使得UI线程可以在空闲时间切片执行可执行的耗时任务,因此,UI线程不会出现卡顿和跳帧的问题,并且减少了UI线程的等待时间,提高了UI线程的资源利用率,为用户带来了更好的体验。

附图说明

通过参考附图阅读下文的详细描述,本公开示例性实施方式的上述以及其他目的、特征和优点将变得易于理解。在附图中,以示例性而非限制性的方式示出了本公开的若干实施方式,其中:

图1为本公开实施方式的任务处理方法的一种应用场景示意图;

图2为本公开实施方式的任务处理方法的流程示意图;

图3为本公开实施方式的任务列表的结构示意图;

图4为本公开实施方式的确定任务的任务处理时长的示意图;

图5为本公开实施方式的执行任务的流程示意图;

图6为本公开实施方式的渲染任务的执行过程示意图;

图7为本公开实施方式的确定当前帧渲染任务的开始时刻和结束时刻的示意图;

图8为本公开实施方式的确定空闲时间切片的流程示意图;

图9为本公开实施方式的存储介质的结构示意图;

图10为本公开实施方式的任务处理装置的结构示意图;

图11为本公开实施方式的计算设备的结构示意图。

在附图中,相同或对应的标号表示相同或对应的部分。

具体实施方式

下面将参考若干示例性实施方式来描述本公开的原理和精神。应当理解,给出这些实施方式仅仅是为了使本领域技术人员能够更好地理解进而实现本公开,而并非以任何方式限制本公开的范围。相反,提供这些实施方式是为了使本公开更加透彻和完整,并且能够将本公开的范围完整地传达给本领域的技术人员。

本领域技术人员知道,本公开的实施方式可以实现为一种系统、装置、设备、方法或计算机程序产品。因此,本公开可以具体实现为以下形式,即:完全的硬件、完全的软件(包括固件、驻留软件、微代码等),或者硬件和软件结合的形式。

根据本公开的实施方式,提出了一种任务处理方法、介质、装置和计算设备。在本文中,需要理解的是,所涉及的术语解释如下:

赫兹(Hertz,简称Hz):是国际单位制中频率的单位,是每秒钟的周期性变动重复次数的计量。每秒钟振动(或振荡、波动)一次为1赫兹。智能终端的LED显示屏的刷新频率为60HZ,表示每秒刷新60次。

帧率(Frame rate):是以帧称为单位的位图图像连续出现在显示器上的频率(速率)。该术语同样适用于胶片和摄像机,计算机图形和动作捕捉系统。帧速率也可以称为帧频率,并以赫兹(Hz)表示。

用户界面(User Interface,简称UI)线程:又称UI线程,能够响应操作系统的特定消息,包括界面消息、鼠标键盘消息、自定义消息、界面绘制计算等,是在普通的子线程(也即worker线程)基础上加上消息循环来实现的,在这个消息循环上不断地获取操作系统或其他线程派发过来的消息(也即,线程里面执行for循环),再根据这个消息找到对应的消息处理对象/函数,如果暂时没有消息需要处理就让UI线程等待,让出中央处理器(centralprocessing unit,简称CPU)的时间片,以此表现出该UI线程一直“在线”的状态,直到某一特定退出消息结束该UI线程。在Android系统上,所有的页面绘制都是在UI线程执行的,因此不能将耗时的任务放在UI线程执行。

子线程:又称worker线程,为了不影响UI线程的长时间任务处理导致的界面操作阻塞,提升用户体验,通过worker线程完成复杂的任务,任务处理完后可以让worker线程立即退出,也可以让worker线程继续等待新的任务,看实际需求。一个处理完任务后不退出而处于等待状态的worker线程相当于UI线程,也即,worker线程可以自己实现一个任务队列,然后不断地获取任务来达到UI线程的效果。

跳帧:在Hz的基础之上,若显示器设定的刷新率是60Hz,也就是16.6ms刷新一次显示器,则每一个16.6ms的阶段需要完成UI的渲染以及UI线程的耗时任务。若这些耗时任务超过了16.6ms,那么下一帧就会跳过渲染,直到当前帧渲染完成之后,才会渲染下一帧,这就是跳帧。

卡顿:通常情况下,人眼的识别连贯图像的速度是24帧/秒,只要连贯图片的速度超过24帧/秒,就认为当前连贯图像很顺畅,若连贯图片的速度低于24帧/秒,就认为当前连贯图像不太连贯。当在跳帧的基上,一次性连续跳了多帧,如10帧,也即166ms,约为6帧/秒,则会明显的感觉到当前的连贯图像迟钝,反应较慢,这就是卡顿。

空闲时间切片:在Hz的基础之上,以60Hz刷新频率的显示器为例,在每一个16.6ms的时间段内,当完成了UI的渲染以及UI线程耗时任务之后,剩下的时间就称为空闲时间切片。

垂直同步(Vertical Synchronization,简称VSYNC)信号:用于将每秒传输帧数(Frames Per Second,简称FPS)和显示器的刷新率进行同步。其目的是避免一种称之为“撕裂”的现象。如果没有垂直同步信号,当引擎渲染的帧数据较快时,显示器刷新速度跟不上,可能就会出现撕裂现也即象,当前显示器正在显示某一帧,另外一帧又触发在显示器上显示。

此外,附图中的任何元素数量均用于示例而非限制,以及任何命名都仅用于区分,而不具有任何限制含义。

另外,本公开所涉及的数据可以为经用户授权或者经过各方充分授权的数据,对数据的采集、传播、使用等,均符合国家相关法律法规要求,本公开实施方式/实施例可以互相组合。

下面参考本公开的若干代表性实施方式,详细阐释本公开的原理和精神。

发明概述

本发明人发现,在Android系统中,通常会有一些耗时任务需要执行,这些耗时任务一般会放在子线程中处理,从而避免出现UI线程(也即主线程)卡顿的情况,但是不可避免的,依然会出现有些任务必须要在UI线程中执行,因此,还是会出现UI线程因为执行过多耗时任务而出现卡顿的情况。相关技术中,为了解决UI线程执行耗时任务而出现卡顿的问题,当UI线程处理完当前时间点的UI渲染任务和用户自定义的耗时任务等耗时任务之后,会执行Android系统提供的任务调度器,以对任务调度器调度的其他耗时任务进行执行。但若UI线程执行任务调度器时过于耗时,依然会导致UI线程卡顿或者跳帧,若需要对任务调度器中的任务进行调整,也无法部分移除任务,只能全部移除任务。因此,相关技术中无法监控Android系统上每帧的渲染开始时刻和渲染结束时刻,无法在应用程序(Application,简称APP)页面启动后的第一个UI帧展示之后开始执行用户自定义的耗时任务,或者统计第一个UI帧的渲染时长;并且,相关技术也无法精准的利用空闲时间切片,当UI线程处于空闲时间时,可能会执行所有的UI线程耗时任务,由于空闲时间切片和UI线程耗时任务都是不确定的耗时,因此UI线程在执行耗时任务时很容易超过一帧的时长16.6ms,从而出现跳帧或者卡顿的问题。

因此,本公开提供了一种任务处理方法,对于UI线程处理的每一帧渲染任务,在渲染任务的执行过程中,可以获取渲染任务的渲染开始时刻和渲染结束时刻,通过渲染开始时刻和渲染结束时刻可以确定渲染任务在UI线程中的任务处理时长,从而通过每一帧的时长和渲染任务在UI线程中的任务处理时长,确定出每一帧的空闲时间切片。然后按照空闲时间切片匹配对应时长的耗时任务,UI线程可以在空闲时间切片中执行对应时长的耗时任务,从而避免执行任务耗时过长导致的UI线程卡顿和跳帧的问题。

在介绍了本公开的基本原理之后,下面具体介绍本公开的各种非限制性实施方式。

应用场景总览

首先参考图1,图1为本公开实施方式的任务处理方法的一种应用场景示意图。在图1中,任务处理方法可以应用于任务处理系统,该任务处理系统可以部署在Android操作系统上,该任务处理系统可以包括渲染耗时监控模块、空闲时间切片模块和任务调度模块。

在该场景中,可以通过渲染耗时监控模块确定Android操作系统上UI线程的每一帧的渲染任务的渲染开始时刻和渲染结束时刻,通过渲染开始时刻和渲染结束时刻,可以确定出每一帧的渲染任务的渲染耗时。空闲时间切片模块可以获取到渲染耗时监控模块监控到的每一帧渲染任务的渲染耗时,然后根据每一帧的总时长和渲染耗时,确定出每一帧的空闲时间切片,也即,每一帧的总时长与渲染耗时之间的差值即为空闲时间切片的时长。任务调度模块可以将UI线程上的耗时任务拆分为多个任务处理时长相同或者不同的子任务,根据每个子任务的任务处理时长,将子任务与空闲时间切片模块确定出的各个空闲时间切片进行匹配,使得将每个子任务在合适的空闲时间切片中执行。

在上述场景中,由于可以监控每一帧的渲染任务的渲染耗时,因此,可以获取到每一帧的空闲时间切片,从而可以将耗时任务分配至合适的空闲时间切片中进行执行,因此,可以避免UI线程的卡顿和跳帧的问题,也可以提高UI线程的时间利用率。

示例性方法

下面结合图1的应用场景,参考图2来描述根据本公开示例性实施方式的任务处理方法。需要注意的是,上述应用场景仅是为了便于理解本公开的精神和原理而示出,本公开的实施方式在此方面不受任何限制。相反,本公开的实施方式可以应用于适用的任何场景。

参考图2,图2为本公开实施方式的任务处理方法的流程示意图,如图2所示,该任务处理方法包括以下步骤:

S201:确定当前帧的空闲时间切片。

在该步骤中,空闲时间切片的起始时刻为用户界面UI线程开始空闲的时刻,空闲时间切片的结束时刻为当前帧的结束时刻。

具体地,同一操作系统的屏幕刷新频率是固定的,因此,每一帧的时长是固定的,UI线程在每一帧执行渲染任务,因此,每一帧都可能存在空闲时间切片。空闲时间切片的起始时刻为UI线程在当前帧开始空闲的时刻,也即,当前帧的渲染任务的执行结束时刻;空闲时间切片的结束时刻为当前帧的结束时刻,也即,空闲时间切片为当前帧的渲染任务执行结束之后到当前帧结束的这个时间段。

S202:获取任务处理时长小于或等于空闲时间切片的目标任务。

具体地,UI线程执行的耗时任务的任务处理时长过长,可能会超过空闲时间切片的时长,导致UI线程的卡顿和跳帧,因此,在进行任务调度时,为了避免UI线程出现卡顿和跳帧的问题,可以在确定了当前帧的空闲时间切片之后,确定适合在该空闲时间切片中执行的目标任务,也即,获取任务处理时长小于或等于空闲时间切片的目标任务,例如,当前帧的空闲时间切片为3ms,则目标任务为3ms及以下的任务。这样在执行目标任务时,UI线程不会出现卡顿或跳帧的问题。

S203:在空闲时间切片内,执行目标任务。

具体地,在获取到目标任务之后,UI线程就可以在空闲时间切片内执行目标任务,由于目标任务的任务处理时长小于或等于空闲时间切片,因此,UI线程不会出现卡顿和跳帧的问题。

本公开的任务处理方法,通过确定当前帧的空闲时间切片,然后获取任务处理时长小于或等于空闲时间切片的目标任务,这样UI线程在空闲时间切片内执行目标任务时,就不会出现卡顿和跳帧的问题,另外,还可以提高UI线程的时间利用率。

在本公开的一个实施例中,获取任务处理时长小于或等于空闲时间切片的目标任务,包括:获取任务列表,任务列表中包括至少一个任务队列,每个任务队列中包含的待处理任务的任务处理时长相同,不同任务队列中包含的待处理任务的任务处理时长不同;在任务列表中确定第一任务队列,第一任务队列对应的任务处理时长小于或等于空闲时间切片;在第一任务队列中确定目标任务。

在该实施例中,在获取任务处理时长小于或等于空闲时间切片的目标任务时,可以先获取包括至少一个任务队列的任务列表,任务列表中的每个任务队列中包含的待处理任务的任务处理时长相同,不同任务队列中包含的待处理任务的任务处理时长不同。在获取到任务列表之后,可以按照空闲时间切片在任务列表中确定对应的第一任务队列,然后在第一任务队列中确定目标任务。

具体地,在确定目标任务时,可以在任务列表中先确定第一任务队列,第一任务队列的数量可以为多个,例如,空闲时间切片的时长为5ms,则第一任务队列可以有5个,分别为1ms对应的任务队列,2ms对应的任务队列,3ms对应的任务队列,4ms对应的任务队列,5ms对应的任务队列。在第一任务队列中确定目标任务时,可以将1ms对应的任务队列中的第一个任务确定为目标任务,也可以将5ms对应的任务队列中的第一个任务确定为目标任务,也可以将上述5个任务队列中任意一个队列的第一个任务确定为目标任务。通过确定空闲时间切片,并通过任务列表确定合适的目标任务,可以避免UI线程执行任务耗时过长导致的卡顿和跳帧的问题,还可以提高UI线程的时间利用率。

可选地,任务列表中的任务队列可以为链表结构。

在本公开的一个实施例中,获取任务列表之前,还包括:采用链表结构构建任务列表中的至少一个任务队列;获取待处理任务;将获取到的待处理任务添加至任务列表中的第二任务队列,得到任务列表,第二任务队列对应的任务处理时长与获取到的待处理任务的任务处理时长相同。

在该实施例中,以Android操作系统为例,屏幕的刷新频率为60Hz/s,也就是16.6ms/帧,因此,帧率的回调是每隔16.6ms一次,从而需要高效的读取任务的任务处理时长。因此,可以采用链表结构构建任务列表中的至少一个任务队列,提高任务队列中存储的任务的增删效率和任务处理时长的查询效率。

具体地,任务列表可以采用哈希映射(HASHMAP)表实现,HASHMAP表中包括关键字KEY和值VALUE,其中,KEY为INT型,以任务的任务处理时长作为KEY,VALUE对应的任务队列为链表结构,用来存储当前任务处理时长KEY对应的所有任务。如图3所示,图3为本公开实施方式的任务列表的结构示意图,在图3中,KEY以1ms到10ms为例,KEY以1ms递增,VALUE为1ms到10ms分别对应的存储有任务的链表,每个链表中以4个任务为例。在实际应用中,KEY的取值可以按需修改,链表中存储的任务也可以按需进行增删。

具体地,在构建完任务列表之后,可以获取待处理任务,然后确定待处理任务的任务处理时长,根据待处理任务的任务处理时长,将待处理任务存储在对应的链表中,也即第二任务队列。

可选地,可以在检测到UI线程空闲时开始获取待处理任务。

在本公开的一个实施例中,将获取到的待处理任务添加至任务列表中的第二任务队列,包括:响应于获取到的待处理任务的任务处理时长小于或等于预设值,将获取到的待处理任务添加至第二任务队列,第二任务队列的数量为一个;响应于获取到的待处理任务的任务处理时长大于预设值,对获取到的待处理任务进行拆分处理,得到多个子任务;按照子任务的任务处理时长,将多个子任务添加至第二任务队列,第二任务队列的数量为多个。

在该实施例中,在将待处理任务添加至第二任务队列中时,可以先确定待处理任务的任务处理时长,若当前任务列表中有可匹配的任务队列,例如,待处理任务的任务处理时长为6ms,任务列表中存在6ms对应的链表,则可以将待处理任务存储至6ms对应的链表中,此时,第二任务队列即为该6ms对应的链表;若当前任务列表中没有可匹配的任务队列,例如,待处理任务的任务处理时长为10ms,任务列表中不存在10ms对应的链表,存在3ms对应的链表和4ms对应的链表,则可以对待处理任务进行拆分处理,得到两个3ms的子任务和一个4ms的子任务,然后将子任务存储在对应的链表中,此时,第二任务队列即为3ms对应的链表和4ms对应的链表。

可选地,通过将待处理任务存储至任务列表中,可以根据空闲时间切片在任务列表中匹配合适的目标任务,从而执行目标任务,因此,可以提高确定目标任务的效率,也可以避免UI线程执行任务时的卡顿和跳帧,还可以提高UI线程的时间利用率。

在本公开的一个实施例中,还包括:确定获取到的待处理任务在预设时间范围内的历史任务处理时长;将历史任务处理时长中的最大值,确定为获取到的待处理任务的任务处理时长。

在该实施例中,每个待处理任务在不同的操作系统中,任务处理时长可能会有所不同,在同一个操作系统中,不同时间待处理任务的任务处理时长可能也会有所不同,因此,可以获取在预设时间范围内的待处理任务的历史任务处理时长,然后确定历史任务处理时长中的最大值,将其确定为当前待处理任务的任务处理时长,从而保证UI线程在执行待处理任务时,不会出现卡顿和跳帧的问题。即使读取到的待处理任务的任务处理时长可能会小于待处理任务的实际执行时长,但仅为几毫秒的差值,UI线程的卡顿和跳帧也可以忽略不计。

举例而言,空闲时间切片为6ms,则需要确定6ms以内能够完成的待处理任务。当前待处理任务的第一次的任务处理时长可以为开发者提供的默认时长(开发者在操作系统上执行后得出的实际任务执行时长),当待处理任务执行一次之后,会将其在当前操作系统上的实际任务处理时长进行保存,后续获取待处理任务的任务处理时长时,会将其历史任务处理时长的最大值取出,作为该待处理任务的任务处理时长。每个待处理任务可以保存最近5次的任务处理时长。如图4所示。

图4为本公开实施方式的确定任务的任务处理时长的示意图,在图4中,以A任务为例,第一次读取A任务的任务处理时长时,无历史任务处理时长,因此,第一次的任务处理时长为默认时长3ms,在第一次执行A任务时,实际的任务耗时为5ms,将5ms进行保存;第二次读取A任务的任务处理时长为5ms,第二次执行A任务时,实际的任务耗时为4ms,将5ms和4ms进行保存;第三次读取A任务的任务处理时长为5ms,第三次执行A任务时,实际的任务耗时为7ms,将5ms、4ms和7ms进行保存;第四次读取A任务的任务处理时长为7ms,第四次执行A任务时,实际的任务耗时为6ms,将5ms、4ms、7ms和6ms进行保存;第五次读取A任务的任务处理时长为7ms,第五次执行A任务时,实际的任务耗时为4ms,将5ms、4ms、7ms、6ms和4ms进行保存;第六次读取A任务的任务处理时长为7ms,第六次执行A任务时,实际的任务耗时为3ms,将4ms、7ms、6ms、4ms和3ms进行保存。

具体地,所有待处理任务的历史任务处理时长的数据会保存在安全数码卡(Secure Digital Memory Card/SD card,简称SD卡)上,在智能终端的APP启动时,子线程进行任务处理时长的数据加载,将数据加载至智能终端的运行内存中,以加快后续读取任务处理时长的速度。在本次待处理任务执行结束之后,需要将获取到的本次任务处理时长更新至运行内存中,等待APP页面关闭时,统一将数据写入至SD卡中。

具体地,在确定了待处理任务的历史任务处理时长之后,可以将待处理任务与历史任务处理时长进行绑定,这样就可以在后续实现快速读取待处理任务的任务处理时长,以便于快速获取与空闲时间切片匹配的待处理任务。

在本公开的一个实施例中,将获取到的待处理任务添加至任务列表中的第二任务队列之前,还包括:将待处理任务与当前帧所在的页面的生命周期进行绑定处理。

在该实施例中,为了避免页面销毁之后,待处理任务未删除导致内存资源浪费,可以将待处理任务与当前帧所在的页面的生命周期进行绑定处理,这样在页面销毁之后,绑定的待处理任务也会自动删除,从而避免内存泄露。

具体地,在将待处理任务与当前帧所在的页面的生命周期进行绑定处理之后,就可以将待处理任务添加至任务列表中。

在本公开的一个实施例中,在空闲时间切片内,执行目标任务之后,还包括:确定并存储目标任务在空闲时间切片内的执行时长;根据执行时长,更新空闲时间切片。

在该实施例中,UI线程在当前的空闲时间切片内执行完目标任务之后,当前帧的空闲时间切片会发生变化,因此,可以确定并存储目标任务在空闲时间切片内的执行时长,然后用执行目标任务前的空闲时间切片的时长减去目标任务的执行时长,得到新的空闲时间切片,从而实现空闲时间切片的更新,以便于后续继续匹配可执行的任务,避免空闲时间切片的浪费。

在本公开的一个实施例中,任务列表中的至少一个任务队列按照对应的任务处理时长从小到大的顺序排列;该任务处理方法还包括:响应于监测到用于表示任务调度超时的标志信息,将任务列表中的第一个非空任务队列确定为第三任务队列;获取第三任务队列中的第一个任务进行执行。

在该实施例中,任务列表中可以包括多个任务队列,每个任务队列对应的KEY为该任务队列中待处理任务的任务处理时长,为了便于待处理任务与空闲时间切片的匹配,也为了便于执行待处理任务,可以按照KEY从小到大的顺序将任务队列进行排序。

具体地,以Android操作系统为例,每一帧的时长为16.6ms,因此,空闲时间切片的最大时长不会超过16.6ms。而在不同操作系统或者智能终端的机型不同时,由于机器性能差异,各个待处理任务的实际执行耗时可能会超过16.6ms,导致某些待处理任务一直无法和空闲时间切片的时长匹配上,从而导致任务调度超时。因此,当任务队列在预设时长内,例如1s内,都没有任何待处理任务被调度执行(60Hz的情况下,1s会有60次的帧率调用,也就是会有60次的任务调度执行),但是任务队列又不为空,则可以说明当前存在调度异常超时的待处理任务,为了保证所有待处理任务的正常执行,可以设置任务调度超时的标志信息。在监测到用于表示任务调度超时的标志信息时,直接获取任务列表中的第一个非空任务队列,也即第三任务队列中的第一个任务进行执行,而无需获取当前帧的空闲时间切片,从而保证任务列表中所有添加的待处理任务,无论是否匹配上空闲时间切片,都会得到执行。

可选地,在监测到用于表示任务调度超时的标志信息之后,可以向开发者上报当前的异常调度任务,由开发者判断此次异常调度的异常原因,该异常原因可以包括智能终端的机器性能出现异常,和/或,异常调度任务拆分不合理。

可选地,在任务列表中获取需要执行的任务时,可以通过在任务列表中查询是否存在任务元素,若任务元素不存在,或已存在的任务元素与空闲时间切片不匹配,则确定任务列表中不存在可执行的子任务。

在本公开的一个实施例中,还包括:在任务执行完成之后,在对应的任务队列中删除执行完成的任务。

在该实施例中,为了节省任务列表的存储空间,在任务执行完成之后,可以在任务队列中将已执行完成的任务进行删除。在执行任务队列中的任务时,由于同一个任务队列中所有任务的任务处理时长相同,因此可以从任务队列中的第一个任务开始执行,执行完之后将该任务删除,然后下一次再执行进行了删除处理后的该任务队列中的第一个任务,从而保证任务队列中的所有任务都是未执行过的,进一步可以提高任务列表中查询任务的效率。

在本公开的一个实施例中,UI线程执行任务的流程也可以如图5所示,图5为本公开实施方式的执行任务的流程示意图,在图5中,UI线程执行任务可以包括如下步骤:

S501:确定是否存在需要添加至任务列表中的待处理任务。

具体地,若存在,则跳转至步骤S502,若不存在,则跳转至步骤S504。

S502:将待处理任务进行数据绑定处理。

具体地,将待处理任务与当前帧所在的页面的生命周期进行绑定,以及将待处理任务与其历史任务处理时长进行绑定。

S503:添加待处理任务。

具体地,可以根据待处理任务的任务处理时长确定是否对待处理任务进行拆分处理,若不对待处理任务进行拆分处理,则按照待处理任务的任务处理时长将待处理任务添加至任务列表中合适的任务队列中,若对待处理任务进行拆分处理,则按照拆分后得到的子任务的任务处理时长将各子任务添加至任务列表中合适的任务队列中。

S504:确定任务列表中是否存在可执行的任务。

具体地,若存在,则跳转至步骤S505,若不存在,则流程结束。

S505:确定当前是否存在用于表示任务调度超时的标志信息。

具体地,若不存在,则跳转至步骤S506,若存在,则跳转至步骤S510。

S506:获取空闲时间切片。

S507:在任务列表中确定与空闲时间切片匹配的任务队列。

S508:确定与空闲时间切片匹配的任务队列中是否存在任务。

具体地,若存在,则跳转至步骤S509,若不存在,则流程结束。

S509:执行与空闲时间切片匹配的任务队列中第一个任务。

S510:获取任务列表中第一个非空队列的第一个任务。

S511:执行第一个非空队列的第一个任务。

在本公开的一个实施例中,确定当前帧的空闲时间切片,包括:获取当前帧的渲染任务的开始时刻和结束时刻;根据开始时刻和结束时刻,确定渲染任务的渲染时长;将当前帧的刷新时长和渲染时长的差值,确定为空闲时间切片,刷新时长通过用户界面的刷新频率确定,刷新时长大于或等于渲染时长。

在该实施例中,以Android操作系统为例,屏幕刷新是60Hz/秒,也就是16.6ms/帧,由于系统在接收到刷新信号(也即垂直同步信号VSYNC信号)时,才会开始进行页面视图树的计算和渲染,因此,每一帧都需要接收到VSYNC信号才会开始执行渲染任务,在下一帧VSYNC信号到来之前,需要完成当前帧的渲染任务。操作系统上的渲染任务分为两个阶段,分别是APP计算阶段的页面视图树的测量、布局、绘制,以及系统层面的渲染,如图6所示。

图6为本公开实施方式的渲染任务的执行过程示意图,在图6中,以8帧为例,每帧的时长为16.6ms,在接收到垂直同步信号VSYNC信号时每帧开始执行渲染任务。APP计算阶段在UI线程中执行,每一帧的渲染(render)函数开始执行页面视图树的测量、布局、绘制,render函数在执行完页面视图树的测量、布局、绘制之后,即可认为当前帧的UI线程的渲染工作已完成,等待接收下一个VSYNC信号;系统渲染阶段在其他线程和/或进程中执行,render函数在执行完页面视图树的测量、布局、绘制之后,系统开始进行渲染,将视图渲染至屏幕上,因此,render函数在执行完页面视图树的测量、布局、绘制之后,UI线程开始空闲,从而可以利用UI线程的空闲时间执行其他的耗时任务,不仅提高了UI线程的时间利用率,还可以避免UI线程执行其他的耗时任务时间较长导致的卡顿和跳帧的问题。

具体地,在APP计算阶段中,由于每一帧需要计算的页面视图树的复杂程度可能不一样,因此图6所示的每一帧的render耗时也是不一样的,从而需要通过监控每一个VSYNC信号到来之后APP计算阶段的render耗时,也即每一帧的渲染任务的开始时刻和结束时刻。根据开始时刻和结束时刻,就可以确定出渲染任务的渲染时长,也即render耗时,从而可以将当前帧的刷新时长和渲染时长的差值确定为空闲时间切片,该刷新时长在图6中为16.6ms。例如,当前帧的刷新时长为16.6ms,render耗时也即渲染时长为6ms,则空闲时间切片为16.6-6=10.6ms。

在本公开的一个实施例中,获取当前帧的渲染开始时刻和渲染结束时刻,包括:调用当前帧的第一监听回调函数,确定渲染开始时刻,第一监听回调函数用于监听渲染任务的开始时刻;调用当前帧的第二监听回调函数,确定渲染结束时刻,第二监听回调函数用于监听渲染任务的结束时刻。

在该实施例中,在当前帧的APP计算阶段,可以在render函数中引入用于APP视图树的计算和屏幕交互渲染的类Choreographer, 由Choreographer对象来监听VSYNC信号,VSYNC信号到来之后,就会通知render进行APP视图树的计算处理, 当APP视图树的计算处理完成之后,Choreographer对象将计算后的数据交给屏幕进行渲染。可选地,可以利用Choreographer对象,通过java虚拟机(Java Virtual Machine,简称JVM)反射的方式来确定渲染任务的开始时刻和结束时刻。

具体地,通过系统钩子(HOOK)机制,确定每一帧的渲染任务的开始时刻和结束时刻,也即通过监听回调函数确定每一帧的渲染任务的开始时刻和结束时刻,监听回调函数包括第一监听回调函数和第二监听回调函数,其中,第一监听回调函数也可以称为开始渲染监听回调函数,第二监听回调函数也可以称为结束渲染监听回调函数。确定每一帧的渲染任务的开始时刻和结束时刻可以如图7所示。

图7为本公开实施方式的确定当前帧渲染任务的开始时刻和结束时刻的示意图,在图7中,在页面视图树的render过程中,可以包括四个回调函数, 分别为输入回调函数input_callback、 动画回调函数animation_callback、遍历回调函数traversal_callback和提交回调函数commit_callback,render通过这四个回调函数完成页面视图树的测量、布局、绘制。在确定渲染任务的开始时刻和结束时刻时, 可以在接收到VSYNC信号之后,在input_callback之前,插入开始渲染监听回调函数,在页面视图树的测量、布局、绘制结束之后,也即在traversal_callback之后,插入结束渲染监听回调函数,这样就可以通过开始渲染监听回调函数确定渲染任务的开始时刻,通过结束渲染监听回调函数确定渲染任务的结束时刻。因此,可以确定出空闲时间切片,从而不仅可以提高UI线程的时间利用率,还可以避免UI线程执行其他的耗时任务时间较长导致的卡顿和跳帧的问题。

可选地,在图7中, 由于commit_callback的耗时为0或者无限接近于0, 因此,结束渲染监听回调函数可以插入在traversal_callback之后,若后续在commit_callback中有需要执行的任务,则也可以将结束渲染监听回调函数插入在commit_callback之后。

在本公开的一个实施例中,确定空闲时间切片的流程也可以如图8所示,图8为本公开实施方式的确定空闲时间切片的流程示意图,在图8中,确定空闲时间切片可以包括如下步骤:

S801:获取当前帧的Choreographer对象。

具体地,可以在APP启动阶段,获取当前帧系统的Choreographer对象。

S802:确定是否监测到垂直同步信号VSYNC信号。

具体地,若是,则跳转至步骤S803,若否,则结束流程。

S803:在Choreographer对象中注入开始渲染监听回调函数,通过开始渲染监听回调函数确定渲染任务的开始时刻。

具体地,在注入开始渲染监听回调函数之前,还需要先创建开始渲染监听回调函数,该开始渲染监听回调函数首次由开发者注入到Choreographer对象中,也即在第一次接收到VSYNC信号时,开发者将开始渲染监听回调函数注入到Choreographer对象中,在后续接收到VSYNC信号时,开始渲染监听回调函数可以自动注入到Choreographer对象中,从而实现监听每一帧的渲染任务的开始时刻,同时记录每一帧的渲染任务的开始时刻。

S804:在Choreographer对象中注入结束渲染监听回调函数,通过结束渲染监听回调函数确定渲染任务的结束时刻。

具体地,在注入结束渲染监听回调函数之前,还需要先创建结束渲染监听回调函数,该结束渲染监听回调函数首次由开发者注入到Choreographer对象中,也即由开发者将结束渲染监听回调函数插入在traversal_callback之后,在后续接每一帧的页面视图树的测量、布局、绘制结束之后,结束渲染监听回调函数可以自动插入在traversal_callback之后,从而实现监听每一帧的渲染任务的结束时刻,同时记录每一帧的渲染任务的结束时刻。

S805:通过开始时刻和结束时刻确定空闲时间切片。

具体地,在监听到每一帧的渲染任务结束之后,就可以通过结束时刻和开始时刻之间的差值确定出渲染任务的渲染耗时,从而通过每一帧的时长与渲染耗时之间的差值,确定出空闲时间切片。

本公开的任务处理方法,通过三部分实现UI线程的碎片时间管理,在帧率耗时监控部分,通过HOOK系统对象Choreographer,注入监听回调函数,以获取当前帧的渲染开始时刻和渲染结束时刻,从而确定当前帧的渲染任务的耗时情况。在空闲时间切片部分,生成当前帧可用的空闲时间切片,然后通过任务调度部分获取当前空闲时间切片内可执行的任务。该任务调度部分主要负责记录每个任务在当前中央处理器(central processingunit,简称CPU)中的执行耗时情况,同时在APP初始化时通过读取CPU中的历史任务执行耗时的数据生成任务耗时记录表,用于给空闲时间切片匹配时间更加精准的任务,然后执行该任务,避免出现UI线程跳帧和卡顿的情况。

因此,本公开的技术方案,可以精准的监控每一帧的渲染任务的渲染耗时,对于线上用户的性能评估会更加准确;可以避免UI线程的跳帧和卡顿的问题,还可以提高UI线程的碎片时间的利用率;还可以实现在不同机型的CPU上具备自动学习功能,当获取第一次的任务执行耗时之后,会将每个任务的执行耗时保存至本地,后续再次使用的时候,会自动调度任务进行执行,从而避免因机型CPU差异导致的任务耗时调度不准确的问题。

示例性介质

在介绍了本公开示例性实施方式的方法之后,接下来,参考图9对本公开示例性实施方式的存储介质进行说明。

参考图9所示,存储介质90中存储着根据本公开的实施方式的用于实现上述方法的程序产品,其可以采用便携式紧凑盘只读存储器(CD-ROM)并包括计算机执行指令,该计算机执行指令用于使计算设备执行本公开所提供的任务处理方法。然而,本公开的程序产品不限于此。

本公开的程序产品可以采用一个或多个可读介质的任意组合。可读介质可以是可读信号介质或者可读存储介质。可读存储介质例如可以为但不限于电、磁、光、电磁、红外线、或半导体的系统、装置或器件,或者任意以上的组合。可读存储介质的更具体的例子(非穷举的列表)包括:具有一个或多个导线的电连接、便携式盘、硬盘、随机存取存储器(RAM)、只读存储器(ROM)、可擦式可编程只读存储器(EPROM或闪存)、光纤、便携式紧凑盘只读存储器(CD-ROM)、光存储器件、磁存储器件、或者上述的任意合适的组合。

可读信号介质可以包括在基带中或者作为载波一部分传播的数据信号,其中承载了计算机执行指令。这种传播的数据信号可以采用多种形式,包括但不限于电磁信号、光信号或上述的任意合适的组合。可读信号介质还可以是可读存储介质以外的任何可读介质。

可以以一种或多种程序设计语言的任意组合来编写用于执行本公开公开操作的计算机执行指令,该程序设计语言包括面向对象的程序设计语言—诸如Java、C++等,还包括常规的过程式程序设计语言—诸如“C”语言或类似的程序设计语言。计算机执行指令可以完全地在用户计算设备上执行、部分地在用户设备上执行、部分在远程计算设备上执行、或者完全在远程计算设备或服务器上执行。在涉及远程计算设备的情形中,远程计算设备可以通过任意种类的网络,包括局域网(LAN)或广域网(WAN),连接到用户计算设备。

示例性装置

在介绍了本公开示例性实施方式的介质之后,接下来,参考图10对本公开示例性实施方式的任务处理装置进行说明,用于实现上述任一方法实施例中的方法,其实现原理和技术效果类似,在此不再赘述。

图10为本公开实施方式的任务处理装置的结构示意图,如图10所示,该任务处理装置1000包括:

确定模块1001,用于确定当前帧的空闲时间切片,空闲时间切片的起始时刻为用户界面UI线程开始空闲的时刻,空闲时间切片的结束时刻为当前帧的结束时刻;

获取模块1002,用于获取任务处理时长小于或等于空闲时间切片的目标任务;

执行模块1003,用于在空闲时间切片内,执行目标任务。

可选地,获取模块1002通过以下步骤实现获取任务处理时长小于或等于空闲时间切片的目标任务:获取任务列表,任务列表中包括至少一个任务队列,每个任务队列中包含的待处理任务的任务处理时长相同,不同任务队列中包含的待处理任务的任务处理时长不同;在任务列表中确定第一任务队列,第一任务队列对应的任务处理时长小于或等于空闲时间切片;在第一任务队列中确定目标任务。

可选地,获取模块1002还用于在获取任务列表之前,采用链表结构构建任务列表中的至少一个任务队列;获取待处理任务;将获取到的待处理任务添加至任务列表中的第二任务队列,得到任务列表,第二任务队列对应的任务处理时长与获取到的待处理任务的任务处理时长相同。

可选地,获取模块1002通过以下步骤实现将获取到的待处理任务添加至任务列表中的第二任务队列:响应于获取到的待处理任务的任务处理时长小于或等于预设值,将获取到的待处理任务添加至第二任务队列,第二任务队列的数量为一个;响应于获取到的待处理任务的任务处理时长大于预设值,对获取到的待处理任务进行拆分处理,得到多个子任务;按照子任务的任务处理时长,将多个子任务添加至第二任务队列,第二任务队列的数量为多个。

可选地,任务处理装置还包括:第一处理模块(未示出),用于确定获取到的待处理任务在预设时间范围内的历史任务处理时长;将历史任务处理时长中的最大值,确定为获取到的待处理任务的任务处理时长。

可选地,获取模块1002还用于在将获取到的待处理任务添加至任务列表中的第二任务队列之前,将待处理任务与当前帧所在的页面的生命周期进行绑定处理。

可选地,任务处理装置还包括:更新模块(未示出),用于在空闲时间切片内,执行目标任务之后,确定并存储目标任务在空闲时间切片内的执行时长;根据执行时长,更新空闲时间切片。

可选地,任务列表中的至少一个任务队列按照对应的任务处理时长从小到大的顺序排列;任务处理装置还包括:第二处理模块(未示出),用于响应于监测到用于表示任务调度超时的标志信息,将任务列表中的第一个非空任务队列确定为第三任务队列;获取第三任务队列中的第一个任务进行执行。

可选地,任务处理装置还包括:删除模块(未示出),用于在任务执行完成之后,在对应的任务队列中删除执行完成的任务。

可选地,确定模块1001通过以下步骤实现确定当前帧的空闲时间切片:获取当前帧的渲染任务的开始时刻和结束时刻;根据开始时刻和结束时刻,确定渲染任务的渲染时长;将当前帧的刷新时长和渲染时长的差值,确定为空闲时间切片,刷新时长通过用户界面的刷新频率确定,刷新时长大于或等于渲染时长。

可选地,确定模块1001通过以下步骤实现获取当前帧的渲染开始时刻和渲染结束时刻:调用当前帧的第一监听回调函数,确定渲染开始时刻,第一监听回调函数用于监听渲染任务的开始时刻;调用当前帧的第二监听回调函数,确定渲染结束时刻,第二监听回调函数用于监听渲染任务的结束时刻。

示例性计算设备

在介绍了本公开示例性实施方式的方法、介质和装置之后,接下来,参考图11对本公开示例性实施方式的计算设备进行说明。

图11显示的计算设备1100仅仅是一个示例,不应对本公开实施例的功能和使用范围带来任何限制。

图11为本公开实施方式的计算设备的结构示意图,如图11所示,计算设备1100以通用计算设备的形式表现。计算设备1100的组件可以包括但不限于:至少一个处理单元1101、至少一个存储单元1102,连接不同系统组件(包括处理单元1101和存储单元1102)的总线1103。其中,至少一个存储单元1102中存储有计算机执行指令;至少一个处理单元1101包括处理器,处理器执行该计算机执行指令,以实现上文描述的方法。

总线1103包括数据总线、控制总线和地址总线。

存储单元1102可以包括易失性存储器形式的可读介质,例如随机存取存储器(RAM)1121和/或高速缓存存储器1122,可以进一步包括非易失性存储器形式的可读介质,例如只读存储器(ROM)1123。

存储单元1102还可以包括具有一组(至少一个)程序模块1124的程序/实用工具1125,这样的程序模块1124包括但不限于:操作系统、一个或者多个应用程序、其它程序模块以及程序数据,这些示例中的每一个或某种组合中可能包括网络环境的实现。

计算设备1100也可以与一个或多个外部设备1104(例如键盘、指向设备等)通信。这种通信可以通过输入/输出(I/O)接口1105进行。并且,计算设备1100还可以通过网络适配器1106与一个或者多个网络(例如局域网(LAN),广域网(WAN)和/或公共网络,例如因特网)通信。如图11所示,网络适配器1106通过总线1103与计算设备1100的其它模块通信。应当理解,尽管图中未示出,可以结合计算设备1100使用其它硬件和/或软件模块,包括但不限于:微代码、设备驱动器、冗余处理单元、外部磁盘驱动阵列、RAID系统、磁带驱动器以及数据备份存储系统等。

应当注意,尽管在上文详细描述中提及了任务处理装置的若干单元/模块或子单元/模块,但是这种划分仅仅是示例性的并非强制性的。实际上,根据本公开的实施方式,上文描述的两个或更多单元/模块的特征和功能可以在一个单元/模块中具体化。反之,上文描述的一个单元/模块的特征和功能可以进一步划分为由多个单元/模块来具体化。

此外,尽管在附图中以特定顺序描述了本公开方法的操作,但是,这并非要求或者暗示必须按照该特定顺序来执行这些操作,或是必须执行全部所示的操作才能实现期望的结果。附加地或备选地,可以省略某些步骤,将多个步骤合并为一个步骤执行,和/或将一个步骤分解为多个步骤执行。

虽然已经参考若干具体实施方式描述了本公开的精神和原理,但是应该理解,本公开并不限于所公开的具体实施方式,对各方面的划分也不意味着这些方面中的特征不能组合以进行受益,这种划分仅是为了表述的方便。本公开旨在涵盖所附权利要求的精神和范围内所包括的各种修改和等同布置。

相关技术
  • 任务处理方法、装置、电子设备及计算机可读存储介质
  • 绩效任务数据处理方法、装置、计算机设备及存储介质
  • 任务处理方法、装置、电子设备及计算机可读存储介质
  • 文本处理方法、装置、设备、计算机设备和存储介质
  • 任务处理方法及装置、电子设备及存储介质
  • 任务处理方法、装置、计算机设备及计算机可读存储介质
  • 计算任务处理方法、装置、计算机设备和存储介质
技术分类

06120115933698