• 2390阅读
  • 16回复

关于嵌入式板上QT的update耗费 [复制链接]

上一主题 下一主题
离线ghldh94
 

只看楼主 倒序阅读 楼主  发表于: 2019-06-26
在把window下的QT应用移植到嵌入式linux中时发现的问题
为此特意做了个test 测试。
界面只有一个widget.  初始化只启动一个timer ,10ms timeout后槽函数中update()。同时qDebug时间戳。
发现在全志的板子上,时间戳几乎要100多ms 才能打印一次。CPU也几乎17%左右降不下来。
这样的效率,做静态UI还好。做动态效果几乎没办法做啊。
有人知道怎么解决这种问题吗?

离线九重水

只看该作者 1楼 发表于: 2019-06-26
首先,Qt的定时器本来就不准,号称高精度的有20%的误差,这是我测试的,其他人不知道。
另外,有测试代码吗?update函数里面你是怎么写的?处理的事情过多也会导致定时延迟处理。
离线liudianwu

只看该作者 2楼 发表于: 2019-06-26
你可以设置什么多不要干,就打印时间试试!肯定是你其他地方有问题!全志H3我都用了好几年了,做产品!
专业各种自定义控件编写+UI定制+输入法定制+视频监控+工业控制+仪器仪表+嵌入式linux+各种串口网络通信,童叟无欺,量大从优,欢迎咨询购买定制!你正好需要,我正好专业!QQ:517216493 微信:feiyangqingyun Email:feiyangqingyun@163.com
群号:853086607(Qt交流大会,雨田哥群,不定期上传作品,解答作品中相关问题!) 312125701(QtQML多多指教群) 46679801(Qt开发技术交流群-5000人大群)
离线ghldh94

只看该作者 3楼 发表于: 2019-06-26
#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
#include <QtDebug>
#include <qdatetime.h>


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    QTimer *timer = new QTimer;
    //新建定时器
    connect(timer,SIGNAL(timeout()),this,SLOT(timetest()));
    //关联定时器计满信号和相应的槽函数
    timer->setTimerType(Qt::PreciseTimer);   //设置高精度
    timer->start(50);
}

void Widget::paintEvent(QPaintEvent *event)
{
   //空的,什么都不做
}

Widget::~Widget()
{
    delete ui;
}

void Widget::timetest()
{
    update();  //更新 ---------  仅仅update一下,耗时数十毫秒,若注释掉则无耗费
    qDebug()<<"timerUpDate"<<QDateTime::currentDateTime();
}
离线ghldh94

只看该作者 4楼 发表于: 2019-06-26
回 liudianwu 的帖子
liudianwu:你可以设置什么多不要干,就打印时间试试!肯定是你其他地方有问题!全志H3我都用了好几年了,做产品! (2019-06-26 14:25) 

请帮我看看,用的T7.  我是没有做其它动作的。另外,用release 重新测试了一下,好了一些,但仍然需要40ms。
离线ghldh94

只看该作者 5楼 发表于: 2019-06-26
回 九重水 的帖子
九重水:首先,Qt的定时器本来就不准,号称高精度的有20%的误差,这是我测试的,其他人不知道。
另外,有测试代码吗?update函数里面你是怎么写的?处理的事情过多也会导致定时延迟处理。[表情]
 (2019-06-26 14:16) 

定时器不准我也知道,所以我有设置  timer->setTimerType(Qt::PreciseTimer);   //设置高精度。
在window下基本偏差不会超过2ms(绘图情况).  开发板上稍大还能接受,但如题我设置的10ms. 结果打印出来全都是偏差数十ms ,这就太大了。
离线九重水

只看该作者 6楼 发表于: 2019-06-26
原来你调用的是QWidget的update函数啊,它要【重新刷新整个界面】,那它可忙了!
而且你要10ms刷新一次,简直忙到脚不沾地的地步。
游戏显卡处理100帧是什么概念?  

我建议你在定时触发这样的函数里面处理非常简单的事情,比如 i++,j++啊,
如果你要定时刷新一些东西,建议计算好最小重绘区域再来重绘,比如仅仅是一秒钟刷新一次时间。
离线九重水

只看该作者 7楼 发表于: 2019-06-26
一句话,由于你调用update的频率太高(相当于游戏100帧),
update函数掉刷新界面的任务提交给qt循环机制,累积了太多的刷新任务,
cpu忙不过来,导致cpu占用率奇高,
同时导致延迟大幅度增加。

如果你非得update,那就一秒一次吧,这样我保证一秒是可以update一次的,绝对不会有重绘任务累积。
离线ghldh94

只看该作者 8楼 发表于: 2019-06-26
回 九重水 的帖子
九重水:一句话,由于你调用update的频率太高(相当于游戏100帧),
update函数掉刷新界面的任务提交给qt循环机制,累积了太多的刷新任务,
cpu忙不过来,导致cpu占用率奇高,
同时导致延迟大幅度增加。
....... (2019-06-26 15:36) 

项目要求是最少得有20ms的频率。我们做的是仪表盘。1s一次岂不是成了时钟秒表了吗 。在window上8ms上下都没有问题,在这块T7上100ms都有问题。 你做H3的时候,没有转盘、指针等对精度要求高的UI吗?应该也会遇到同样问题
离线九重水

只看该作者 9楼 发表于: 2019-06-26
回 ghldh94 的帖子
ghldh94:项目要求是最少得有20ms的频率。我们做的是仪表盘。1s一次岂不是成了时钟秒表了吗[表情] 。在window上8ms上下都没有问题,在这块T7上100ms都有问题。 你做H3的时候,没有转盘、指针等对精度要求高的UI吗?应该也会遇到同样问题 (2019-06-26 16:55) 

这种需求也可以理解的(不过说句实话,人眼的反应时间20ms不需要这么短时间,25帧40ms是可以的)。
我前面也说过方法,你需要精确计算刷新区域(就一个圆,相信很快可以计算出来),这样情况下,你将需要刷新的区域大为缩小,CPU处理起来就简单得多!
离线ghldh94

只看该作者 10楼 发表于: 2019-06-26
回 ghldh94 的帖子
ghldh94:项目要求是最少得有20ms的频率。我们做的是仪表盘。1s一次岂不是成了时钟秒表了吗[表情] 。在window上8ms上下都没有问题,在这块T7上100ms都有问题。 你做H3的时候,没有转盘、指针等对精度要求高的UI吗?应该也会遇到同样问题 (2019-06-26 16:55) 

而且总的CPU占用只要超过10%就会开始delay。8%都不怎么delay,14%delay很明显。 并不是“奇高”哦。 所以怀疑这里是不是系统有什么限制住了单只应用的资源占用。
离线ghldh94

只看该作者 11楼 发表于: 2019-06-26
回 九重水 的帖子
九重水:这种需求也可以理解的(不过说句实话,人眼的反应时间20ms不需要这么短时间,25帧40ms是可以的)。
我前面也说过方法,你需要精确计算刷新区域(就一个圆,相信很快可以计算出来),这样情况下,你将需要刷新的区域大为缩小,CPU处理起来就简单得多![表情] (2019-06-26 17:09) 

若果是和绘制区域大小有关我也就不纠结了,实际是我不做绘制也一样的delay。
离线ghldh94

只看该作者 12楼 发表于: 2019-06-26
只要调用到update  ,  不管paintEvent中有无绘图工作,都一样delay的。 嗯,40ms勉强也能接受吧。可是T7都没能做到,目前看最少是100多。对了,我还尝试了把timer 放到子线程中执行。这样qDebug打出来的时间是精确了,没有delay,意味着update也是按照我的20ms 调用。但实际跑起来,它是把7~8个update 合并执行一次paintEvent (QT是这样的机制)。 所以这种方式也是不行。归结起来,是一个奇怪的现象:只要CPU占用达到10%多,就上不去,到不了20%。 同时时钟就delay执行任务。
本帖提到的人: @liudianwu
离线九重水

只看该作者 13楼 发表于: 2019-06-26
回 ghldh94 的帖子
ghldh94:只要调用到update  ,  不管paintEvent中有无绘图工作,都一样delay的。 嗯,40ms勉强也能接受吧。可是T7都没能做到,目前看最少是100多。对了,我还尝试了把timer 放到子线程中执行。这样qDebug打出来的时间是精确了,没有delay,意味着update也是按照我的20m .. (2019-06-26 17:20) 

就一个仪表盘而已,100MS刷新频率根本就不碍事。
如果非得跟游戏一样刷新,全职H7应该有GPU吧,直接弄个窗口用GPU给仪表盘得了。

不过,老刘说他做过很多,你问一下他怎么用一个CPU干所有活,包括10ms刷新这么变态的事,哈哈。
1条评分金钱+5
ghldh94 金钱 +5 热心就2个字 2019-06-27
离线ghldh94

只看该作者 14楼 发表于: 2019-06-27
回 九重水 的帖子
九重水:就一个仪表盘而已,100MS刷新频率根本就不碍事。
如果非得跟游戏一样刷新,全职H7应该有GPU吧,直接弄个窗口用GPU给仪表盘得了。
不过,老刘说他做过很多,你问一下他怎么用一个CPU干所有活,包括10ms刷新这么变态的事,哈哈。
....... (2019-06-26 21:51) 

嗯嗯,还是感谢你多次帮忙回复。权当个讨论。
昨天我有回头继续去尝试。 其实问题的关键不是100ms或10ms(这个是测试,实际会慢一些) ,要知道,这个数据是在test中做的,实际做项目,那肯定要绘图的,跑得会慢更多,非常多。我是指这样的CPU效率肯定不对,实际贴图出来成秒表了快。用top命令去分析,CPU最多也只占用18%,都上不去20%,明明还有很大余地,就是没用到。用GPU绘图我也想到了。但要去研究下,麻烦多了,有些动画我担心做不了。
离线ghldh94

只看该作者 15楼 发表于: 2019-09-02
回来结题了,希望给遇到同类问题的朋友参考:
1、用QOpenGlWidget   取代QWidget  , 速度快了N倍。 这是本质上的改变。
2、速度慢的根源是CPU 读取图片文件慢,改成大图片预先加载进内存,速度快一截,这是第二关键;
3、接着第2点,发现scaled 函数、SmoothTransformation 变换大小,很耗时,所以同样 预先处理好。另外drawpie 画扇形,速度简直龟爬,这个函数只能在电脑用用了,嵌入式板子改用其它方式吧。
4、IO流~  。 我发现即使qDebug 打印都是有影响的, 更别说操作文件之类的了。所以要么在多线程中操作,主线程打印我都删掉了。
以上,基本解决了我遇到的问题。 不过缺点也有,占用内存变大了~还有启动速度慢了一丢丢~
离线akecbz

只看该作者 16楼 发表于: 2020-07-01
正好要做啊,刷新要求高,及时雨                        
快速回复
限100 字节
 
上一个 下一个