日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

QML 性能优化建议(一)

發(fā)布時間:2025/1/21 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 QML 性能优化建议(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

時間因素

開發(fā)程序時,必須盡可能實現(xiàn)一致的60幀/秒刷新率。60幀/秒意味著每幀之間大約有16毫秒可以進(jìn)行處理,其中包括將繪圖基元上傳到圖形硬件所需的處理。

那么,就需要注意以下幾個重要的點:

1.盡可能使用異步,事件驅(qū)動編程
2.使用工作線程進(jìn)行重要處理
3.永遠(yuǎn)不要手動控制事件循環(huán)
4.在阻塞函數(shù)中,每幀的花費不要超過幾毫秒

如果不這樣做,那么將會發(fā)生調(diào)整,影響用戶體驗。

注意:永遠(yuǎn)不應(yīng)該使用的模式是創(chuàng)建自己的QEventLoop或調(diào)用QCoreApplication :: processEvents(),以避免在從QML調(diào)用的C ++代碼塊中阻塞。這樣做非常危險,因為當(dāng)在信號處理程序或綁定中輸入事件循環(huán)時,QML引擎繼續(xù)運行其他綁定,動畫,轉(zhuǎn)換等。然后這些綁定會導(dǎo)致副作用,例如,破壞包含整體層次結(jié)構(gòu)事件循環(huán)。

剖析

最重要的提示是:使用Qt Creator附帶的QML分析器。了解應(yīng)用程序在何處花費時間將使您能夠?qū)W⒂趯嶋H存在的問題區(qū)域,而不是可能存在的問題區(qū)域。有關(guān)如何使用QML分析工具的更多信息,請參閱Qt creator 幫助文檔。

如果不進(jìn)行分析而直接去優(yōu)化代碼,可能效果并不會很明顯,借助分析器將會更快的定位到消耗性能的模塊,然后再進(jìn)行重新設(shè)計,以便提高性能。

JavaScript代碼

大多數(shù)QML應(yīng)用程序?qū)⒁詣討B(tài)函數(shù)、信號處理程序和屬性綁定表達(dá)式的形式包含大量JavaScript代碼。這通常不是問題,由于QML引擎中的一些優(yōu)化,例如對綁定編譯器所做的那些優(yōu)化,它可以(在某些用例中)比調(diào)用C ++函數(shù)更快。但是,必須注意確保不會意外觸發(fā)不必要的處理。

綁定

QML中有兩種類型的綁定:優(yōu)化綁定和非優(yōu)化綁定。保持綁定表達(dá)式盡可能簡單是一個好主意,因為QML引擎使用優(yōu)化的綁定表達(dá)式求值程序,它可以評估簡單的綁定表達(dá)式,而無需切換到完整的JavaScript執(zhí)行環(huán)境。與更復(fù)雜(非優(yōu)化)的綁定相比,這些優(yōu)化的綁定的評估效率更高。優(yōu)化綁定的基本要求是在編譯時必須知道所訪問的每個符號的類型信息。

綁定表達(dá)式時要避免的事情,以達(dá)到最大的優(yōu)化:

1.聲明中間JavaScript變量
2.訪問“var”屬性
3.調(diào)用JavaScript函數(shù)
4.構(gòu)造閉包或在綁定表達(dá)式中定義函數(shù)
5.訪問直接評估范圍之外的屬性
6.寫作其他屬性作為副作用

立即評估范圍可以概括為它包含:

1.表達(dá)式范圍對象的屬性(對于綁定表達(dá)式,這是屬性綁定所屬的對象)
2.組件中任何對象的ID
3.組件中根項的屬性

來自其他組件的對象和任何此類對象的屬性,以及JavaScript導(dǎo)入中定義或包含的符號都不在直接評估范圍內(nèi),因此不會優(yōu)化訪問任何這些對象的綁定。

類型轉(zhuǎn)換

使用JavaScript的一個主要成本是,在大多數(shù)情況下,當(dāng)訪問QML類型的屬性時,會創(chuàng)建一個包含底層C ++數(shù)據(jù)(或?qū)λ囊?#xff09;的外部資源的JavaScript對象。在大多數(shù)情況下,這是不會太影響性能,但在其他情況下,它可能相當(dāng)消耗性能。比如是將C ++ QVariantMap Q_PROPERTY分配給QML“variant”屬性。列表也可能是有損性能的,盡管(特定類型的序列的QList為int, qreal,布bool,QString,和QUrl)應(yīng)該相對來說不會太影響, 其他列表類型可能會帶來昂貴的轉(zhuǎn)換成本(創(chuàng)建新的JavaScript數(shù)組,逐個添加新類型,從C ++類型實例到JavaScript值的每類型轉(zhuǎn)換)。

在一些基本屬性類型(例如“string”和“url”屬性)之間轉(zhuǎn)換也可能很影響性能。使用最接近的匹配屬性類型將避免不必要的轉(zhuǎn)換。

如果必須將QVariantMap公開給QML,請使用“var”屬性而不是“variant”屬性。一般來說,對于來自QtQuick 2.0及更新版本的每個用例,“property var”應(yīng)該被認(rèn)為優(yōu)于“property variant” (注意“property variant”被標(biāo)記為過時),因為它允許真正的JavaScript引用存儲(可以減少某些表達(dá)式中所需的轉(zhuǎn)換次數(shù))。

解決屬性

雖然在某些情況下可以緩存和重用查找結(jié)果,但如果可能的話,最好完全避免完成不必要的工作。

在下面的示例中,我們有一個經(jīng)常運行的代碼塊(在這種情況下,它是顯式循環(huán)的內(nèi)容;但它可能是一個通常評估的綁定表達(dá)式,例如),在其中,我們解決了具有“rect”id及其“color”屬性的對象多次調(diào)用:

// bad.qml import QtQuick 2.3Item {width: 400height: 200Rectangle {id: rectanchors.fill: parentcolor: "blue"}function printValue(which, value) {console.log(which + " = " + value);}Component.onCompleted: {var t0 = new Date();for (var i = 0; i < 1000; ++i) {printValue("red", rect.color.r);printValue("green", rect.color.g);printValue("blue", rect.color.b);printValue("alpha", rect.color.a);}var t1 = new Date();console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations");} }

我們可以在塊中只解析一次公共基數(shù):

// good.qml import QtQuick 2.3Item {width: 400height: 200Rectangle {id: rectanchors.fill: parentcolor: "blue"}function printValue(which, value) {console.log(which + " = " + value);}Component.onCompleted: {var t0 = new Date();for (var i = 0; i < 1000; ++i) {var rectColor = rect.color; // resolve the common base.printValue("red", rectColor.r);printValue("green", rectColor.g);printValue("blue", rectColor.b);printValue("alpha", rectColor.a);}var t1 = new Date();console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations");} }

只需這一簡單的改變就可以顯著提高性能。請注意,上面的代碼可以進(jìn)一步改進(jìn)(因為在循環(huán)處理期間查找的屬性永遠(yuǎn)不會改變),通過將屬性解析提升出循環(huán),如下所示:

// better.qml import QtQuick 2.3Item {width: 400height: 200Rectangle {id: rectanchors.fill: parentcolor: "blue"}function printValue(which, value) {console.log(which + " = " + value);}Component.onCompleted: {var t0 = new Date();var rectColor = rect.color; // resolve the common base outside the tight loop.for (var i = 0; i < 1000; ++i) {printValue("red", rectColor.r);printValue("green", rectColor.g);printValue("blue", rectColor.b);printValue("alpha", rectColor.a);}var t1 = new Date();console.log("Took: " + (t1.valueOf() - t0.valueOf()) + " milliseconds for 1000 iterations");} }

屬性綁定

如果更改了引用的任何屬性,則將重新評估屬性綁定表達(dá)式。因此,綁定表達(dá)式應(yīng)盡可能簡單。

如果你有一個循環(huán)來進(jìn)行某些處理,但只有處理的最終結(jié)果很重要,通常最好更新一個臨時累加器,然后將其分配給需要更新的屬性,而不是逐步更新屬性本身,以避免在累積的中間階段觸發(fā)重新評估結(jié)合表達(dá)。

以下的例子說明了這一點:

// bad.qml import QtQuick 2.3Item {id: rootwidth: 200height: 200property int accumulatedValue: 0Text {anchors.fill: parenttext: root.accumulatedValue.toString()onTextChanged: console.log("text binding re-evaluated")}Component.onCompleted: {var someData = [ 1, 2, 3, 4, 5, 20 ];for (var i = 0; i < someData.length; ++i) {accumulatedValue = accumulatedValue + someData[i];}} }

onCompleted處理程序中的循環(huán)導(dǎo)致“text”屬性綁定被重新評估六次(然后導(dǎo)致依賴于文本值的任何其他屬性綁定,以及onTextChanged信號處理程序,每次重新評估時間,并列出每次顯示的文本)。在這種情況下,這顯然是不必要的,因為我們只關(guān)心最終的值。
那么,以上代碼可以改成這樣:

// good.qml import QtQuick 2.3Item {id: rootwidth: 200height: 200property int accumulatedValue: 0Text {anchors.fill: parenttext: root.accumulatedValue.toString()onTextChanged: console.log("text binding re-evaluated")}Component.onCompleted: {var someData = [ 1, 2, 3, 4, 5, 20 ];var temp = accumulatedValue;for (var i = 0; i < someData.length; ++i) {temp = temp + someData[i];}accumulatedValue = temp;} }

序列提示

如前所述,某些序列類型很快(例如,QList ,QList ,QList ,QList < QString >,QStringList和QList < QUrl >),而其他序列類型則要慢得多。除了盡可能使用這些類型而不是較慢類型之外,還需要注意一些其他與性能相關(guān)的語法以獲得最佳性能。

首先,對于序列類型的兩種不同的實現(xiàn):一個是當(dāng)序列是Q_PROPERTY一個的QObject的(我們稱此為參考序列),另一個用于在序列從返回Q_INVOKABLE一個功能的QObject(我們將這稱為復(fù)制序列)。

通過QMetaObject :: property()讀取和寫入引用序列,因此讀取和寫入QVariant。這意味著從JavaScript更改序列中任何元素的值將導(dǎo)致三個步驟發(fā)生:將從QObject讀取完整序列(作為QVariant,但隨后轉(zhuǎn)換為正確類型的序列); 指定索引處的元素將在該序列中更改; 并且完整的序列將被寫回QObject(作為QVariant)。

復(fù)制序列更簡單,因為實際序列存儲在JavaScript對象的資源數(shù)據(jù)中,因此不會發(fā)生讀取/修改/寫入循環(huán)(而是直接修改資源數(shù)據(jù))。

因此,對參考序列的元素的寫入將比寫入復(fù)制序列的元素慢得多。實際上,寫入N元素參考序列的單個元素與將N元素復(fù)制序列分配給該參考序列的成本相當(dāng)大,因此通常最好修改臨時復(fù)制序列,然后將結(jié)果分配給計算過程中的參考序列。

假設(shè)以下C ++類型存在,并且已經(jīng)正常注冊過:

class SequenceTypeExample : public QQuickItem {Q_OBJECTQ_PROPERTY (QList<qreal> qrealListProperty READ qrealListProperty WRITE setQrealListProperty NOTIFY qrealListPropertyChanged)public:SequenceTypeExample() : QQuickItem() { m_list << 1.1 << 2.2 << 3.3; }~SequenceTypeExample() {}QList<qreal> qrealListProperty() const { return m_list; }void setQrealListProperty(const QList<qreal> &list) { m_list = list; emit qrealListPropertyChanged(); }signals:void qrealListPropertyChanged();private:QList<qreal> m_list; };

以下示例在多次循環(huán)中寫入引用序列的元素,從而導(dǎo)致性能下降:

// bad.qml import QtQuick 2.3 import Qt.example 1.0SequenceTypeExample {id: rootwidth: 200height: 200Component.onCompleted: {var t0 = new Date();qrealListProperty.length = 100;for (var i = 0; i < 500; ++i) {for (var j = 0; j < 100; ++j) {qrealListProperty[j] = j;}}var t1 = new Date();console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");} }

由表達(dá)式引起的內(nèi)部循環(huán)中的QObject屬性讀取和寫入"qrealListProperty[j] = j"使得此代碼非常不理想。相反,更好的一種方法是:

// good.qml import QtQuick 2.3 import Qt.example 1.0SequenceTypeExample {id: rootwidth: 200height: 200Component.onCompleted: {var t0 = new Date();var someData = [1.1, 2.2, 3.3]someData.length = 100;for (var i = 0; i < 500; ++i) {for (var j = 0; j < 100; ++j) {someData[j] = j;}qrealListProperty = someData;}var t1 = new Date();console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");} }

其次,如果屬性中的任何元素發(fā)生變化,則會發(fā)出屬性的更改信號。如果你對序列屬性中的特定元素有很多綁定,最好創(chuàng)建一個綁定到該元素的動態(tài)屬性,并將該動態(tài)屬性用作綁定表達(dá)式中的符號而不是sequence元素,因為它將只有在其值發(fā)生變化時才會重新評估綁定。

// bad.qml import QtQuick 2.3 import Qt.example 1.0SequenceTypeExample {id: rootproperty int firstBinding: qrealListProperty[1] + 10;property int secondBinding: qrealListProperty[1] + 20;property int thirdBinding: qrealListProperty[1] + 30;Component.onCompleted: {var t0 = new Date();for (var i = 0; i < 1000; ++i) {qrealListProperty[2] = i;}var t1 = new Date();console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");} }

請注意,即使在循環(huán)中僅修改索引2處的元素,也會重新評估三個綁定,因為更改信號的粒度是整個屬性已更改。因此,添加中間綁定有時可能是有益的:

// good.qml import QtQuick 2.3 import Qt.example 1.0SequenceTypeExample {id: rootproperty int intermediateBinding: qrealListProperty[1]property int firstBinding: intermediateBinding + 10;property int secondBinding: intermediateBinding + 20;property int thirdBinding: intermediateBinding + 30;Component.onCompleted: {var t0 = new Date();for (var i = 0; i < 1000; ++i) {qrealListProperty[2] = i;}var t1 = new Date();console.log("elapsed: " + (t1.valueOf() - t0.valueOf()) + " milliseconds");} }

在上面的示例中,每次僅重新評估中間綁定,從而導(dǎo)致顯著的性能提升。

值類型提示

值類型屬性(font,color,vector3d等)具有類似的QObject屬性,并將通知語義更改為序列類型屬性。因此,上面給出的序列提示也適用于值類型屬性。雖然它們通常不是值類型的問題(因為值類型的子屬性的數(shù)量通常遠(yuǎn)小于序列中元素的數(shù)量),所以重新評估的綁定數(shù)量的任何增加不必要地會對績效產(chǎn)生負(fù)面影響。

其他JavaScript對象

不同的JavaScript引擎提供不同的優(yōu)化。Qt Quick 2使用的JavaScript引擎針對對象實例化和屬性查找進(jìn)行了優(yōu)化,但它提供的優(yōu)化依賴于某些標(biāo)準(zhǔn)。如果你的應(yīng)用程序不符合標(biāo)準(zhǔn),則JavaScript引擎會回退到“慢速路徑”模式,性能會更差。因此,請始終盡量確保您符合以下條件:

1.盡可能避免使用eval()
2.不要刪除對象的屬性

總結(jié)

以上是生活随笔為你收集整理的QML 性能优化建议(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 免费a v视频 | 免费视频日韩 | 九九热视频精品 | 天堂在线一区 | 午夜免费大片 | 在线观看黄色小视频 | 91视频免费视频 | 一区二区三区视频在线观看 | 韩国电影一区二区三区 | 久久综合色视频 | 日本久久久久久久久 | 日韩精品免费一区二区三区 | 日韩精品一区二区三区高清免费 | 久免费一级suv好看的国产 | 91黄版 | 国产精品1页 | 成人毛片观看 | 欧洲一区在线观看 | av日日夜夜 | 人妻精品久久久久中文字幕69 | 亚洲黄色在线免费观看 | 爱爱视频网 | 亚洲熟妇国产熟妇肥婆 | 国产女人爽到高潮a毛片 | 欧美亚一区二区三区 | 噜噜噜精品欧美成人 | 精品无码久久久久久久久久 | 男人的av| 正在播放一区二区 | 亚洲成人黄色小说 | 亚洲高清久久久 | 毛片一区二区三区 | 国产一区欧美一区 | 性按摩玩人妻hd中文字幕 | 国产精品一区二区亚洲 | www中文字幕在线观看 | 亚洲伦理视频 | 超碰96在线 | 亚洲精品无amm毛片 国内一区二区三区 | 午夜写真片福利电影网 | 激情五月综合色婷婷一区二区 | 青青导航| 欧美成人黄色小视频 | 日本在线高清 | 青青草免费观看 | 性色国产成人久久久精品 | 91偷拍富婆spa盗摄在线 | 久久国产香蕉视频 | 欧美日韩亚洲国产综合 | 日韩久久久久 | 在线日韩成人 | 综合久久久久久 | 久久久久久亚洲中文字幕无码 | 欧美少妇一级片 | 中文字幕精品一区二 | 日韩在线观看你懂的 | 国产一区二区视频在线播放 | 高清av免费 | 日本不卡1| 久久亚洲av无码西西人体 | 久久久夜夜夜 | 波多野吉衣一区二区三区 | 涩涩涩999 | 国产又粗又猛又爽又黄av | 色噜av| 日本成人在线播放 | 日本大胆裸体做爰视频 | 欧美少妇xxx | 中国大陆毛片 | 日韩午夜伦 | 亚洲永久免费观看 | 日本免费毛片 | 91性高潮久久久久久久久 | 日韩精品伦理 | 91成人在线观看高潮 | 午夜专区 | 日韩免费不卡视频 | 亚洲av无码一区东京热久久 | 国内精品少妇 | 欧美在线高清 | 国产伦精品一区二区三区四区视频 | 91成人免费在线观看视频 | 久久久男人天堂 | 国产中文在线视频 | 黄色免费入口 | 成人夜色视频 | 日韩亚洲欧美一区二区三区 | 性欧美xxxx| 亚洲精品99久久久久中文字幕 | 日本网站免费 | 成人一区二 | 欧美第九页 | 91精品小视频 | 色性网站| 久久国产劲爆∧v内射 | 国产成人欧美一区二区三区的 | 中文字幕亚洲综合 | 亚洲国产精品午夜久久久 | 上海女子图鉴 |