赞
踩
前面好早写过一个文章,说明如何把LVGL移到RV1109上的操作,使用DRM方式!但出现刷新效率不高的问题!
因为一直没有真正的应用在产品中,所以也就放下了!
最近开发上需要考虑低成本,低内存的方案,所以后续考虑使用LVGL上来做UI,所以这里捡回来再炒一次!
这里还是使用的LV_DEMO中的lv_demo_benchmark来测试的!
代码见前一相关的文:LVGL - RV1109 LVGL UI开发-01
先找到了为什么刷新FPS如此低的原因,主要耗时花在了:
lvgl_drm_flush->display_commit_ex->drm_commit_ex->drmCommit
上面!
这样导致UI的线程绘图也很慢!
最开始想使用双缓存的方式来提交,但看代码drmCommit是整屏修改提交的!不过对drm里的这个commit底层操作还是不太了解!
还是把耗时的这个操作分开操作!使用另一个线程来commit,这样只要在另一个线程中,如是UI线程有调用lvgl_drm_flush 这个后,发送一个消息通知刷新线程drm commit操即可!
代码修改很简单,在 drm_commit_ex 中使用一个mutex和cond来通知另一个线程:
#ifdef DRM_COMMIT_THREAD
printf("commit request!!!!!!!!!!!\n");
pthread_mutex_lock(&g_commit_mutex);
pthread_cond_broadcast(&g_commit_cond);
pthread_mutex_unlock(&g_commit_mutex);
#else
ret = drmCommit(&disp->buf[num], disp->width, disp->height, 0, 0, &disp->dev, disp->plane_type);
if (ret) {
fprintf(stderr, "display commit error, ret = %d\n", ret);
}
#endif
这里用了一个宏 DRM_COMMIT_THREAD 来控制!
在另一个线程中主要处理如下,即把drmCommit动作放在这里来操作:
#ifdef DRM_COMMIT_THREAD void* dsiplay_commit_thread_process(void* data) { int ret = 0; while(g_commit_thread_start_flag) { pthread_mutex_lock(&g_commit_mutex); pthread_cond_wait(&g_commit_cond, &g_commit_mutex); pthread_mutex_unlock(&g_commit_mutex); //printf("dsiplay_commit_thread_process!!!!!!............\n"); ret = drmCommit(&g_disp.buf[g_num], g_disp.width, g_disp.height, 0, 0, &g_disp.dev, g_disp.plane_type); if (ret) { fprintf(stderr, "display commit error, ret = %d\n", ret); } usleep(1000 * 40); } } int display_commit_thread_start() { int ret = 0; pthread_t pid = 0; pthread_attr_t attr; ret = pthread_attr_init(&attr); if(ret != 0) { printf("start pthread_attr_init failure!!!\n"); return -1; } ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if(ret != 0) { pthread_attr_destroy(&attr); printf( "pthread_attr_setdetachstate PTHREAD_CREATE_DETACHED failure!!!\n"); return -1; } ret = pthread_create(&pid, &attr, dsiplay_commit_thread_process, NULL); if(ret == 0) { printf(" pthread_create OK! \n"); }else{ printf(" pthread_create failure!! \n"); pthread_attr_destroy(&attr); return -1; } pthread_attr_destroy(&attr); return 0; } #endif
下面是 lv_demo_widgets 的统计数据:
FPS统计方式,这里统计drmCommit花费的时间,看一定时长里能提交多少次:
ts = _clockTime_getCurrentMscTime(); ret = drmCommit(&g_disp.buf[g_num], g_disp.width, g_disp.height, 0, 0, &g_disp.dev, g_disp.plane_type); if (ret) { fprintf(stderr, "display commit error, ret = %d\n", ret); } commit_count++; //usleep(1000 * 40); commit_count_cost_time += _clockTime_checkLostMscTime(ts); if(commit_count >= 64 || commit_count_cost_time > 1000 * 30) { int fps = commit_count / (commit_count_cost_time / 1000.0); printf("FPS:%d\n", fps); commit_count = 0; commit_count_cost_time = 0; } }
FPS:81
FPS:86
FPS:77
FPS:80
FPS:79
FPS:83
FPS:76
FPS:77
FPS:93
FPS:82
FPS:83
FPS:72
FPS:82
FPS:80
FPS:80
top - 15:57:46 up 6:57, 2 users, load average: 1.40, 0.84, 0.85
Tasks: 106 total, 3 running, 46 sleeping, 1 stopped, 0 zombie
%Cpu0 : 3.0/21.8 25[||||||||||||||||||||||||| ]
%Cpu1 : 25.7/23.8 50[|||||||||||||||||||||||||||||||||||||||||||||||||| ]
GiB Mem : 7.9/0.876 [ ]
GiB Swap: 0.0/0.000 [ ]
PID USER PR NI VIRT RES %CPU %MEM TIME+ S COMMAND
1 root 20 0 2.0m 0.2m 0.0 0.0 0:00.51 S init
102 root 20 0 2.0m 0.2m 0.0 0.0 0:00.05 S `- syslogd
105 root 20 0 2.0m 0.2m 0.0 0.0 0:00.04 S `- klogd
Result of FPS:47 FPS:80 Result of FPS:40 FPS:78 Result of FPS:46 FPS:74 Result of FPS:40 FPS:74 Result of FPS:42 FPS:83 Result of FPS:28 FPS:79 Result of FPS:50 Result of FPS:51 FPS:77 Result of FPS:48 FPS:77 Result of FPS:47 FPS:73 Result of FPS:42 FPS:75 Result of FPS:41 FPS:79 Result of FPS:49 FPS:75 Result of FPS:51 FPS:77 Result of FPS:50 FPS:78 Result of FPS:50 Result of FPS:50 FPS:80 Result of FPS:48 FPS:76
top - 16:03:47 up 7:03, 2 users, load average: 2.10, 1.93, 1.38 Tasks: 107 total, 2 running, 45 sleeping, 1 stopped, 0 zombie %Cpu0 : 1.0/11.8 13[||||||||||||| ] %Cpu1 : 68.6/16.7 85[|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ] GiB Mem : 7.8/0.876 [ ] GiB Swap: 0.0/0.000 [ ] PID USER PR NI VIRT RES %CPU %MEM TIME+ S COMMAND 1 root 20 0 2.0m 0.2m 0.0 0.0 0:00.51 S init 102 root 20 0 2.0m 0.2m 0.0 0.0 0:00.05 S `- syslogd 105 root 20 0 2.0m 0.2m 0.0 0.0 0:00.04 S `- klogd 120 root 20 0 2.7m 1.9m 0.0 0.2 0:00.22 S `- udevd 573 root 20 0 1.9m 0.1m 0.0 0.0 0:00.00 S `- dropbear 1113 root 20 0 2.3m 1.6m 0.0 0.2 0:12.49 S `- dropbear 1114 root 20 0 2.0m 1.5m 0.0 0.2 0:00.01 S `- sh 1189 root 20 0 2.8m 1.6m 0.0 0.2 0:28.82 T `- top 1220 root 20 0 2.8m 1.6m 1.9 0.2 0:07.22 R `- top 628 root 20 0 1.4m 0.1m 0.0 0.0 0:00.00 S `- input-event-dae 851 root 20 0 2.0m 0.3m 0.0 0.0 0:00.02 S `- login 852 root 20 0 2.0m 1.6m 0.0 0.2 0:00.62 S `- sh 893 root 20 0 1.4m 0.2m 0.0 0.0 0:00.32 S `- wdt_deamon 1225 root 20 0 39.4m 14.7m 84.5 1.6 0:25.70 R `- pupa_face 2 root 20 0 0.0m 0.0m 0.0 0.0 0:00.03 S kthreadd 3 root 0 -20 0.0m 0.0m 0.0 0.0 0:00.00 I `- rcu_gp 4 root 0 -20 0.0m 0.0m 0.0 0.0 0:00.00 I `- rcu_par_gp 8 root 0 -20 0.0m 0.0m 0.0 0.0 0:00.00 I `- mm_percpu_wq 9 root 20 0 0.0m 0.0m 0.0 0.0 0:01.78 S `- ksoftirqd/0 10 root 20 0 0.0m 0.0m 0.0 0.0 1:17.11 I `- rcu_preempt 11 root 20 0 0.0m 0.0m 0.0 0.0 0:00.00 I `- rcu_sched 12 root 20 0 0.0m 0.0m 0.0 0.0 0:00.00 I `- rcu_bh 13 root rt 0 0.0m 0.0m 0.0 0.0 0:00.11 S `- migration/0 14 root 20 0 0.0m 0.0m 0.0 0.0 0:00.00 S `- cpuhp/0 15 root 20 0 0.0m 0.0m 0.0 0.0 0:00.00 S `- cpuhp/1 16 root rt 0 0.0m 0.0m 0.0 0.0 0:00.02 S `- migration/1
分开线程处理后,刷新率立即就上来了,UI线程的FPS在跑 lv_demo_benchmark时,平均commit可以跑到70FPS.
CPU占用率上,不过明显的上升了,使用单线程方式时,CPU占用率在只在5%上下,使用多线程方式时,CPU平均在15%左右,连续操作甚至50%以上!
所以还是还是需要控制一下FPS,这里在dsiplay_commit_thread_process加一个usleep操作.
在跑lv_demo_widgets这个示例时,第二个tab页的 Analytics 界面,能看到仪表盘的每一秒的跳动了,之前的代码是直接跳秒的。
FPS:24 Result of FPS:40 Result of FPS:37 Result of FPS:38 FPS:24 Result of FPS:33 Result of FPS:25 Result of FPS:25 FPS:24 Result of FPS:25 Result of FPS:23 Result of FPS:35 FPS:24 Result of FPS:26 Result of FPS:29 Result of FPS:25 Result of FPS:29 FPS:24 Result of FPS:24 Result of FPS:21 Result of FPS:16 FPS:24
top - 16:17:17 up 7:16, 2 users, load average: 1.08, 0.66, 0.86 Tasks: 106 total, 1 running, 46 sleeping, 1 stopped, 0 zombie %Cpu(s): 21.3/19.3 41[|||||||||||||||||||||||||||||||||||||||| ] GiB Mem : 7.8/0.876 [ ] GiB Swap: 0.0/0.000 [ ] PID USER PR NI VIRT RES %CPU %MEM TIME+ S COMMAND 1 root 20 0 2.0m 0.2m 0.0 0.0 0:00.51 S init 102 root 20 0 2.0m 0.2m 0.0 0.0 0:00.05 S `- syslogd 105 root 20 0 2.0m 0.2m 0.0 0.0 0:00.04 S `- klogd 120 root 20 0 2.7m 1.9m 0.0 0.2 0:00.22 S `- udevd 573 root 20 0 1.9m 0.1m 0.0 0.0 0:00.00 S `- dropbear 1113 root 20 0 2.3m 1.6m 1.0 0.2 0:13.36 S `- dropbear 1114 root 20 0 2.0m 1.5m 0.0 0.2 0:00.01 S `- sh 1189 root 20 0 2.8m 1.6m 0.0 0.2 0:28.82 T `- top 1220 root 20 0 2.8m 1.6m 1.9 0.2 0:24.25 R `- top 628 root 20 0 1.4m 0.1m 0.0 0.0 0:00.00 S `- input-event-dae 851 root 20 0 2.0m 0.3m 0.0 0.0 0:00.02 S `- login 852 root 20 0 2.0m 1.6m 0.0 0.2 0:00.63 S `- sh 893 root 20 0 1.4m 0.2m 0.0 0.0 0:00.33 S `- wdt_deamon 1234 root 20 0 39.4m 14.5m 62.1 1.6 1:05.77 S `- pupa_face 2 root 20 0 0.0m 0.0m 0.0 0.0 0:00.04 S kthreadd 3 root 0 -20 0.0m 0.0m 0.0 0.0 0:00.00 I `- rcu_gp 4 root 0 -20 0.0m 0.0m 0.0 0.0 0:00.00 I `- rcu_par_gp 8 root 0 -20 0.0m 0.0m 0.0 0.0 0:00.00 I `- mm_percpu_wq 9 root 20 0 0.0m 0.0m 0.0 0.0 0:01.84 S `- ksoftirqd/0 10 root 20 0 0.0m 0.0m 1.0 0.0 1:19.85 I `- rcu_preempt 11 root 20 0 0.0m 0.0m 0.0 0.0 0:00.00 I `- rcu_sched
在使用单线程时,lv_demo_widgets在操作,如果是在刷新界面时,很明显有时是无法反应你的触摸操作的,改用多线程后,响应基本是很实时.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。