https://developernote.com/2022/08/qt-signal-is-ten-times-slower-than-a-virtual-function/ DeveloperNote.com A software developer's blog Skip to content * Home * My GitHub * My Apps * My CV * Contact 11 08 22 Leave a comment QT signal is ten times slower than a virtual function Posted by dmitriano | QT | I defined a QT Object that contains an integer value and uses QT signal along with awl::Observable based on virtual functions to notify the subscribers when the value changes: #include "Awl/Observable.h" #include namespace test { class NotifyValueChanged { public: virtual void onValueChanged() = 0; }; class ValueObject : public QObject, public awl::Observable { Q_OBJECT public: Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged) void notifyValueChanged() { Notify(&NotifyValueChanged::onValueChanged); } signals: void valueChanged(); private: int value() const { return m_val; } void setValue(int val) { if (m_val != val) { m_val = val; emit valueChanged(); } } int m_val = 0; }; } Then I defined the subscriber (or observer) object: namespace test { class ObserverObject : public QObject, public awl::Observer { Q_OBJECT public: void onValueChanged() override { ++m_count; } void onValueChangedSignal() { ++m_count; } std::size_t count() const { return m_count; } private: std::size_t m_count = 0; }; } Then I created 1000 observers and notified them 100000 times with both mechanisms: using namespace test; QTIL_UNIT_TEST(SignalTest) { QTIL_ATTRIBUTE(size_t, observer_count, 1000); QTIL_ATTRIBUTE(size_t, emit_count, 100000); { ValueObject object; std::vector observers(observer_count); for (ObserverObject& observer : observers) { QObject::connect(&object, &ValueObject::valueChanged, &observer, &ObserverObject::onValueChangedSignal, Qt::DirectConnection); } { awl::StopWatch sw; for (size_t i = 0; i < emit_count; ++i) { emit object.valueChanged(); } context.logger.debug(qtil::Format() << "QT signal: " << sw); } for (ObserverObject& observer : observers) { AWT_ASSERT(observer.count() == emit_count); } } { ValueObject object; std::vector observers(observer_count); for (ObserverObject& observer : observers) { object.Subscribe(&observer); } { awl::StopWatch sw; for (size_t i = 0; i < emit_count; ++i) { emit object.notifyValueChanged(); } context.logger.debug(qtil::Format() << "Virtual function: " << sw); } for (ObserverObject& observer : observers) { AWT_ASSERT(observer.count() == emit_count); } } } If I compile this code with MSVC2022 Compiler Version 19.32.31332 for Windows 64bit and repeat the test ten times I get the following output: QT signal: 00:00:01.841 Virtual function: 00:00:00.179 QT signal: 00:00:01.782 Virtual function: 00:00:00.185 QT signal: 00:00:01.761 Virtual function: 00:00:00.181 QT signal: 00:00:01.739 Virtual function: 00:00:00.187 QT signal: 00:00:01.752 Virtual function: 00:00:00.183 QT signal: 00:00:01.714 Virtual function: 00:00:00.179 QT signal: 00:00:01.715 Virtual function: 00:00:00.174 QT signal: 00:00:01.721 Virtual function: 00:00:00.173 QT signal: 00:00:01.726 Virtual function: 00:00:00.179 QT signal: 00:00:01.690 Virtual function: 00:00:00.175 MSVC Performance profiler displays this: [image-6] [image-5] If I access the sender from ObserverObject as follows: void onValueChangedSignal() { sender(); ++m_count; } QT signal becomes 16 time slower than the virtual function: QT signal: 00:00:03.060 Virtual function: 00:00:00.215 QT signal: 00:00:02.916 Virtual function: 00:00:00.181 QT signal: 00:00:02.945 Virtual function: 00:00:00.181 QT signal: 00:00:02.996 Virtual function: 00:00:00.187 QT signal: 00:00:03.031 Virtual function: 00:00:00.183 QT signal: 00:00:03.034 Virtual function: 00:00:00.185 QT signal: 00:00:03.011 Virtual function: 00:00:00.178 QT signal: 00:00:03.047 Virtual function: 00:00:00.187 QT signal: 00:00:03.071 Virtual function: 00:00:00.185 QT signal: 00:00:03.111 Virtual function: 00:00:00.186 Profiler displays this: [image-7] [image-8] So per second I can call 558,659,217 virtual function, 59,171,597 signals without sender and 32,562,683 signals with sender (the formula for virtual functions is 1000 * 100000 * (1 / 0.179)). Assume I receive 100,000 trades per second from some crypo exchange and if one trade triggers 100 signals than I have 10.000.000 signals per second that is something comparable with the maximum. Leave a Reply Cancel reply Your email address will not be published. Required fields are marked * [ ] [ ] [ ] [ ] [ ] [ ] [ ] Comment * [ ] Name * [ ] Email * [ ] Website [ ] [Post Comment] [ ] [ ] [ ] [ ] [ ] [ ] [ ] D[ ] * Search for: [ ] [Search] * Categories + CMS (13) o Joomla (7) o WordPress (6) + Cryptocurrencies (33) o BEAM (1) o BTC (1) o BTG (1) o ETH (6) o RVN (2) o USDT (2) o XCH (1) o XMR (1) o XRP (1) + Databases (22) o MS SQL (1) o MySQL (5) o Oracle (14) o SQLite (3) + Development environments (9) + English (1) + Graphics (11) o DirectX (2) o OpenGL (9) + Hardware (13) o Motherboards (2) o PSU (1) o Video cards (8) + Network and Internet (2) + Operating Systems (113) o Android (27) o CentOS (2) o HiveOS (2) o iOS (5) o Mac OS X (10) o Ubuntu (48) o Windows (36) + Platforms and frameworks (89) o .NET (14) o QT (51) o UWP (19) o Win32 (9) o Xamarin (1) + Programming languages (84) o Bash (2) o C# (11) o C++ (48) o Java (1) o JavaScript (2) o PHP (14) o QML (8) o XAML (5) + Uncategorized (4) + Web Servers (11) o Apache (3) o IIS (2) o Nginx (6) * Tag Cloud binance ccxt cpp-serialization docker entity-framework gdal git hyper-v json mail mining openssl ssl virtuemart visual-studio VPS vuejs wcf web-service wix wlw wpf xml-rpc * Recent Comments + Jeff on How to compile BOOST with MS Visual Studio 2010-2017 + felaja on Building QT 6.3.1 with OpenSSL for Windows + Anton K. on Experimentation with OpenSSL and QT configuration on Windows + dmitriano on Mining NEOXA on HiveOS with 3GB cards + Anton K. on Building QT 6.2.2 for Windows and Android * Home * My GitHub * My Apps * My CV * Contact