当前位置: 首页 > news >正文

做网站银川深圳网站运营托管

做网站银川,深圳网站运营托管,建设职业注册中心网站,国内seo排名分析主要针对百度相关代码参考#xff1a;https://gitcode.net/coloreaglestdio/qtcpp_demo/-/tree/master/qt_event_signal 1.问题的由来 在对 taskBus 进行低延迟改造时#xff0c;避免滥用信号与槽起到了较好的作用。笔者在前一篇文章中#xff0c;叙述了通过避免广播式地播发信号…相关代码参考https://gitcode.net/coloreaglestdio/qtcpp_demo/-/tree/master/qt_event_signal 1.问题的由来 在对 taskBus 进行低延迟改造时避免滥用信号与槽起到了较好的作用。笔者在前一篇文章中叙述了通过避免广播式地播发信号以及频繁的 new 与 delete 来提高软件无线电(SDR)平台的吞吐。近期考虑到跨线程异步操作其实事件QEvent可能更加适合点对点的调用遂把taskBus的主数据流转使用 Events 进行了改造收到了大概5-10ms的提升。 这个提升还是没有达到我的期望因为印象里信号与槽是非常慢的。那么问题来了跨线程 SignalSlots 与 Events 到底谁要快为什么快以及快多少呢 2. 回顾“信号槽很慢”的印象的源头 在经典的Qt文档里有一段对信号与槽性能选择的性能描述 Compared to callbacks, signals and slots are slightly slower because of the increased flexibility they provide, although the difference for real applications is insignificant. In general, emitting a signal that is connected to some slots,is approximately ten times slower than calling the receivers directly, with non-virtual function calls.“与回调相比信号和插槽的速度稍慢因为它们提供了更大的灵活性尽管实际应用程序的差异并不显著。通常发射连接到某些插槽的信号比直接调用接收器使用非虚拟函数调用慢大约十倍。” 这就是印象的源头了。不过带着上述问题仔细阅读发现还有更多的解释 This is the overhead required to locate the connection object, to safely iterate over all connections (i.e. checking that subsequent receivers have not been destroyed during the emission), and to marshall any parameters in a generic fashion. While ten non-virtual function calls may sound like a lot, its much less overhead than any new or delete operation, for example.As soon as you perform a string, vector or list operation that behind the scene requires new or delete, the signals and slots overhead is only responsible for a very small proportion of the complete function call costs. The same is true whenever you do a system call in a slot; or indirectly call more than ten functions. The simplicity and flexibility of the signals and slots mechanism is well worth the overhead, which your users wont even notice.“这是定位连接对象、安全地迭代所有连接即检查后续接收器在发射过程中是否未被破坏以及以通用方式整理任何参数所需的开销。虽然十个非虚拟函数调用听起来可能很多但它的开销比任何new操作或delete操作都要小得多。一旦执行了一个字符串、向量或列表操作而该操作在后台需要新建或删除则信号和插槽开销只占整个函数调用成本的一小部分。每当您在插槽中进行系统调用时情况也是如此或者间接调用十多个函数。信号和插槽机制的简单性和灵活性非常值得开销而您的用户甚至不会注意到这一点。” 会不会上次的优化起到关键作用的不是信号与槽改成了直接函数调用而是把频繁new delete换成静态内存导致的提升我立刻进行了测试发现的确如此。 new 和 delete的开销远远大于 signalslots的开销 3. 编程进行专门测试 我们使用Qt专门对信号与槽、事件这两种跨线程传递消息的方法来进行测试。设计测试由两个对象之间互相以最快速度乒乓消息为场景如下图所示 #mermaid-svg-XXWjAjefRJon0lf8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XXWjAjefRJon0lf8 .error-icon{fill:#552222;}#mermaid-svg-XXWjAjefRJon0lf8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XXWjAjefRJon0lf8 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-XXWjAjefRJon0lf8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XXWjAjefRJon0lf8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XXWjAjefRJon0lf8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XXWjAjefRJon0lf8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XXWjAjefRJon0lf8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XXWjAjefRJon0lf8 .marker.cross{stroke:#333333;}#mermaid-svg-XXWjAjefRJon0lf8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XXWjAjefRJon0lf8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XXWjAjefRJon0lf8 .cluster-label text{fill:#333;}#mermaid-svg-XXWjAjefRJon0lf8 .cluster-label span{color:#333;}#mermaid-svg-XXWjAjefRJon0lf8 .label text,#mermaid-svg-XXWjAjefRJon0lf8 span{fill:#333;color:#333;}#mermaid-svg-XXWjAjefRJon0lf8 .node rect,#mermaid-svg-XXWjAjefRJon0lf8 .node circle,#mermaid-svg-XXWjAjefRJon0lf8 .node ellipse,#mermaid-svg-XXWjAjefRJon0lf8 .node polygon,#mermaid-svg-XXWjAjefRJon0lf8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XXWjAjefRJon0lf8 .node .label{text-align:center;}#mermaid-svg-XXWjAjefRJon0lf8 .node.clickable{cursor:pointer;}#mermaid-svg-XXWjAjefRJon0lf8 .arrowheadPath{fill:#333333;}#mermaid-svg-XXWjAjefRJon0lf8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XXWjAjefRJon0lf8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XXWjAjefRJon0lf8 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-XXWjAjefRJon0lf8 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-XXWjAjefRJon0lf8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XXWjAjefRJon0lf8 .cluster text{fill:#333;}#mermaid-svg-XXWjAjefRJon0lf8 .cluster span{color:#333;}#mermaid-svg-XXWjAjefRJon0lf8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XXWjAjefRJon0lf8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 时戳消息 时戳消息 Object1 Object2 含有时戳的消息可以用来计算和统计平均延迟消息生成和被处理的时差以及最终的处理能力。 测试分为信号-槽测试事件测试以及单线程对比调用测试。测试进行10000次调用并模拟实际程序对传递的消息进行一些处理如产生一定长度的字符串。 通过观察不同长度下的开销即可直挂感受消息传递开销与处理开销的占比。 3.1 用于测试的消息体 消息体既用于信号与槽测试也用于Event测试以及直接调用。这样参数中都直接new消息对大家是公平的。 testevent.h---------------#include QEvent #include time.h #include QString class TestMsg : public QEvent { private:static QEvent::Type m_testEvt;static QEvent::Type m_startEvt;static QEvent::Type m_startSig;static QEvent::Type m_quit;clock_t m_clk 0;QString m_dummyLongStr; public:TestMsg(clock_t clk);~TestMsg();inline clock_t clock() {return m_clk;}inline void fillStr(int len){for (int i0;ilen;i){m_dummyLongStr.push_back((char)(i*37%6432));}} public:static inline QEvent::Type type() {return m_testEvt;}static inline QEvent::Type startEvt() {return m_startEvt;}static inline QEvent::Type startSig() {return m_startSig;}static inline QEvent::Type quitEvt() {return m_quit;} };//testevent.cpp--------------- #include testevent.h #include QDebug //Regisit a event QEvent::Type TestMsg::m_testEvt (QEvent::Type)QEvent::registerEventType(); QEvent::Type TestMsg::m_startEvt (QEvent::Type)QEvent::registerEventType(); QEvent::Type TestMsg::m_startSig (QEvent::Type)QEvent::registerEventType(); QEvent::Type TestMsg::m_quit (QEvent::Type)QEvent::registerEventType();TestMsg::TestMsg(clock_t clk):QEvent(m_testEvt),m_clk(clk) {} TestMsg::~TestMsg() {} 消息体含有一个clock时戳用于计算传递耗时。同时有一个fillStr的耗时操作用于模拟真实的有效数据处理。 3.2 测试对象 测试对象直接派生自 QObject将在线程中执行测试。为了模拟信号与槽的 meta 开销设置了26组信号与槽进行交叉连接并用第16组进行测试。 #ifndef TESTOBJ_H #define TESTOBJ_H#include QObject #include QEvent #include testevent.h class TestObj : public QObject {Q_OBJECT public:explicit TestObj(QObject *parent nullptr);void setBuddy(TestObj * buddy) {m_buddy buddy;buddy-m_buddy this;}void runDirectCall(); public slots:void test_slot1(QEvent * evt){}//...void test_slot16(QEvent * evt);//...void test_slot26(QEvent * evt){} signals:void test_sig1(QEvent * evt);//...void test_sig26(QEvent * evt);void evt_finished();void sig_finished(); protected:void customEvent(QEvent *) override; private:clock_t m_nFirstClkSig -1;quint32 m_nCount_Sigs 0;clock_t m_nFirstClkEvt -1;quint32 m_nCount_Evts 0;clock_t m_nFirstClkDir -1;quint32 m_nCount_Dir 0; private:TestObj * m_buddy nullptr; private:void run_signal();void run_event(); private:void direct_call(QEvent * evt); };#endif // TESTOBJ_H 无论以何种接口获得 TestMsg都执行相同的操作 //以信号槽为例 void TestObj::test_slot16(QEvent * evt) {clock_t curr_clk clock();if (m_nFirstClkSig-1)m_nFirstClkSig curr_clk;TestMsg * e dynamic_castTestMsg *(evt);if (e){m_nCount_Sigs;e-fillStr(fillStrLen);if (m_nCount_SigstestCounts){QTextStream strm(stdout);strm objectName() QString().asprintf( (%llX) run %d Signals, total costs %.2lf ms, AVG cost %.2lf us / test.\n,(unsigned long long)this,(int)(m_nCount_Sigs),1e3 * (curr_clk - m_nFirstClkSig) / CLOCKS_PER_SEC,1e6 * (curr_clk - m_nFirstClkSig) / CLOCKS_PER_SEC / testCounts);strm.flush();emit sig_finished();}delete e;} }void TestObj::run_signal() {for (int i0;itestCounts;i)emit test_sig16(new TestMsg(clock())); } 3.3 测试方法 在 main函数中进行测试: #include QCoreApplication #include QThread #include testevent.h #include testobj.h int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);clock_t clk_start clock();printf(StartClk %d\n,clk_start);QThread::msleep(100);QThread * thread1 new QThread;QThread * thread2 new QThread;TestObj * obj1 new TestObj;TestObj * obj2 new TestObj;obj1-setObjectName(OBJ1);obj2-setObjectName(OBJ2);obj1-setBuddy(obj2);obj1-connect(obj1,TestObj::test_sig1,obj2,TestObj::test_slot16,Qt::QueuedConnection);//...obj1-connect(obj1,TestObj::test_sig26,obj2,TestObj::test_slot16,Qt::QueuedConnection);obj1-connect(obj2,TestObj::test_sig16,obj1,TestObj::test_slot1,Qt::QueuedConnection);//...obj1-connect(obj2,TestObj::test_sig16,obj1,TestObj::test_slot26,Qt::QueuedConnection);obj1-moveToThread(thread1);obj2-moveToThread(thread2);thread1-start();thread2-start();printf(Test signals slots, Events...\n);QCoreApplication::processEvents();a.connect (obj1,TestObj::sig_finished,[]()-void{QThread::msleep(1000);QCoreApplication::postEvent(obj1,new QEvent(TestMsg::startEvt()));});a.connect (obj2,TestObj::sig_finished,[]()-void{QThread::msleep(1000);QCoreApplication::postEvent(obj2,new QEvent(TestMsg::startEvt()));});a.connect (obj1,TestObj::evt_finished,[]()-void{QThread::msleep(1000);QCoreApplication::postEvent(obj1,new QEvent(TestMsg::quitEvt()));});a.connect (obj2,TestObj::evt_finished,[]()-void{QThread::msleep(1000);QCoreApplication::postEvent(obj2,new QEvent(TestMsg::quitEvt()));});QThread::msleep(1000);QCoreApplication::processEvents();QCoreApplication::postEvent(obj1,new QEvent(TestMsg::startSig()));QCoreApplication::postEvent(obj2,new QEvent(TestMsg::startSig()));a.processEvents();thread1-wait();thread2-wait();QThread::msleep(2000);obj1-runDirectCall();printf(Finished.\n);thread1-deleteLater();thread2-deleteLater();obj1-deleteLater();obj2-deleteLater();QThread::msleep(1000);QCoreApplication::processEvents();return 0; } 4. 测试结果 测试环境i7 10代 win11 Mingw64 Qt6.6 4.1 Debug, Strlen0,20000次 StartClk 2 Test signals slots, Events... OBJ1 (1AD52AD73E0) run 20000 Signals, total costs 2089.00 ms, AVG cost 104.45 us / test. OBJ2 (1AD52AD74C0) run 20000 Signals, total costs 32.00 ms, AVG cost 1.60 us / test. OBJ2 (1AD52AD74C0) run 20000 Events, total costs 14.00 ms, AVG cost 0.70 us /test. OBJ1 (1AD52AD73E0) run 20000 Events, total costs 27.00 ms, AVG cost 1.35 us /test. Test Direct Call... OBJ1 (1AD52AD73E0) run 20000 Direct Calls, total costs 6.00 ms, AVG cost 0.30 us / test. Finished.4.2 Debug, Strlen1000,20000次 StartClk 2 Test signals slots, Events... OBJ1 (21AFB83BBA0) run 20000 Signals, total costs 2541.00 ms, AVG cost 127.05 us / test. OBJ2 (21AFB83B820) run 20000 Signals, total costs 1630.00 ms, AVG cost 81.50 us / test. OBJ2 (21AFB83B820) run 20000 Events, total costs 1373.00 ms, AVG cost 68.65 us /test. OBJ1 (21AFB83BBA0) run 20000 Events, total costs 1403.00 ms, AVG cost 70.15 us /test. Test Direct Call... OBJ1 (21AFB83BBA0) run 20000 Direct Calls, total costs 1377.00 ms, AVG cost 68.85 us / test. Finished.4.3 Release, Strlen0,100000次 StartClk 5 Test signals slots, Events... OBJ1 (294D24BB5F0) run 100000 Signals, total costs 2236.00 ms, AVG cost 22.36 us / test. OBJ2 (294D24BB930) run 100000 Signals, total costs 25.00 ms, AVG cost 0.25 us / test. OBJ2 (294D24BB930) run 100000 Events, total costs 12.00 ms, AVG cost 0.12 us /test. OBJ1 (294D24BB5F0) run 100000 Events, total costs 38.00 ms, AVG cost 0.38 us /test. Test Direct Call... OBJ1 (294D24BB5F0) run 100000 Direct Calls, total costs 14.00 ms, AVG cost 0.14 us / test. Finished.4.4 Release, Strlen1000100000次 StartClk 4 Test signals slots, Events... OBJ1 (154799851A0) run 100000 Signals, total costs 1358.00 ms, AVG cost 13.58 us / test. OBJ2 (154799854E0) run 100000 Signals, total costs 620.00 ms, AVG cost 6.20 us / test. OBJ2 (154799854E0) run 100000 Events, total costs 543.00 ms, AVG cost 5.43 us /test. OBJ1 (154799851A0) run 100000 Events, total costs 547.00 ms, AVG cost 5.47 us /test. Test Direct Call... OBJ1 (154799851A0) run 100000 Direct Calls, total costs 527.00 ms, AVG cost 5.27 us / test. Finished.5. 结果分析 可以看见 Release下Event 和 直接调用的性能几乎完全一样。Debug下略慢。Release下如果发射的信号只对应一个槽则比直接调用的性能稍微差一些但远没有10倍的差距比如Obj2发射的某个信号只连接到Obj1 的1个槽其实区别不大。Release下如果发射的信号对应多个槽则性能显著下降正如obj1发射的一个信号连接到多个槽结果就很耗时。发射的信号会给每个槽都走一遭。如果存在大量的new\delete则无论何方式区别都不大。new/delete非常耗时。 6. 开发建议 对于密集的点对点异步调用显然是Event比较好。如果是广播性质的多对多Event需要循环则使用信号与槽会利于开发。此外信号与槽会自动维护双方的可用性在目的析构后不再调用槽。Events因为要给入指针则必须自己确保指针的有效性。 提高速度的关键还是使用静态内存避免频繁new、delete。 7. 改进效果 taskBus的异步调用最后一步队列操作使用Event而不是信号来通知线程干活只获得了大概10ms的延迟优化是因为大部分延迟实际是在缓存、滤波器上并不在信号-槽中。使用了QEvent后构造的全通无线网络在 128kbps的带宽下还是要稍微顺畅一些。
http://www.yayakq.cn/news/4589/

相关文章:

  • 网站删除代码稷山网站建设
  • 宿主选择 网站建设做企业网站哪家公司好
  • 手机做推广比较好的网站怎样自己做网站赚钱吗
  • 苏州网站设计服务免费注册网站域名可以用吗
  • 上海网站开发公司排名温州专业手机网站制作哪家便宜
  • 精品课程网站建设的背景及意义网站建设没付尾款
  • 网站开发数据库设计怎么建设淘客自己的网站、
  • 济南冰河世纪网站建设青海小学网站建设
  • 企业网站seo案例分析新手学做百度联盟网站
  • 网页美工设计软件seo营销是什么意思
  • 营销网站开发系统北京建设信源公司网站
  • 旌阳区黄河开发建设网站怎样做中考成绩查询网站
  • 怎么在网站做推广2023年天津市施工招标公告时间
  • 网站建设公司浙江华企祝明电子商务网站建设实验报告
  • 网站浏览器兼容性问题wordpress 4.5 中文404
  • 深圳网站建设排行化妆品网站建设项目计划书
  • 公司网站创建重庆seo排名技术
  • 天津网站优化公司哪家专业建站精灵网站模板
  • 写作网站投稿平台网页设计资料的网站
  • 山西龙采网站建设合同网站换域名
  • 云安区学校网站建设统计表大连开发区社保网站
  • 网站长期建设运营计划书做门户网站建设多少钱
  • 公司的网站备案手续只用网站开发VS就安装那些就够了
  • 图片滤镜网站开发做网站的详细流程
  • 南山模板网站建设公司wordpress点击下载
  • 制作企业网站平坝网站建设
  • 网站流量怎么做乡1万做一个手机app大概需要多少钱
  • 泉州住房和城乡建设网站策划与设计一个电子商务网站
  • 珠海做网站找哪家公司个人网站建设目标
  • 做网站用的字体是什么所有浏览器大全图片