QtBase  v6.3.1
tst_bench_qobject.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 #include <QtCore>
29 #include <QtWidgets/QTreeView>
30 #include <qtest.h>
31 #include "object.h"
32 #include <qcoreapplication.h>
33 #include <qdatetime.h>
34 
35 enum {
38 };
39 
40 class tst_QObject : public QObject
41 {
43 private slots:
44  void signal_slot_benchmark();
45  void signal_slot_benchmark_data();
46  void signal_many_receivers();
47  void signal_many_receivers_data();
48  void qproperty_benchmark_data();
49  void qproperty_benchmark();
50  void dynamic_property_benchmark();
51  void connect_disconnect_benchmark_data();
52  void connect_disconnect_benchmark();
53  void receiver_destroyed_benchmark();
54 
55  void stdAllocator();
56 };
57 
59 {
60  Q_OBJECT
61 public:
63  {
64  }
65 };
66 
67 template<class T>
68 inline void allocator()
69 {
70  // We need to allocate certain amount of objects otherwise the new implementation
71  // may re-use the previous allocation, hiding the somehow high cost of allocation. It
72  // also helps us to reduce the noise ratio, which is high for memory allocation.
73  //
74  // The check depends on memory allocation performance, which is quite non-deterministic.
75  // When a new memory is requested, the new operator, depending on implementation, is trying
76  // to re-use existing, already allocated for the process memory. If there is not enough, it
77  // asks OS to give more. Of course the first case is faster then the second. In the same
78  // time, from an application perspective the first is also more likely.
79  //
80  // As a result, depending on which use-case one wants to test, it may be recommended to run this
81  // test in separation from others, to "force" expensive code path in the memory allocation.
82  //
83  // The time based results are heavily affected by background noise. One really needs to
84  // prepare OS (no other tasks, CPU and RAM reservations) to run this test, or use
85  // instruction counting which seems to be less fragile.
86 
87  const int count = 256 * 1024;
88 
89  QScopedPointer<T> objects[count];
91  for (int i = 0; i < count; ++i)
92  objects[i].reset(new T);
93  for (int i = 0; i < count; ++i)
94  objects[i].reset();
95  }
96 }
97 
98 void tst_QObject::stdAllocator()
99 {
100  allocator<QObjectUsingStandardAllocator>();
101 }
102 
103 struct Functor {
104  void operator()(){}
105 };
106 
107 void tst_QObject::signal_slot_benchmark_data()
108 {
109  QTest::addColumn<int>("type");
110  QTest::newRow("simple function") << 0;
111  QTest::newRow("single signal/slot") << 1;
112  QTest::newRow("multi signal/slot") << 2;
113  QTest::newRow("unconnected signal") << 3;
114  QTest::newRow("single signal/ptr") << 4;
115  QTest::newRow("functor") << 5;
116 }
117 
118 void tst_QObject::signal_slot_benchmark()
119 {
120  QFETCH(int, type);
121 
122  Object singleObject;
123  Object multiObject;
124  Functor functor;
125  singleObject.setObjectName("single");
126  multiObject.setObjectName("multi");
127 
128  if (type == 5) {
129  QObject::connect(&singleObject, &Object::signal0, functor);
130  } else if (type == 4) {
131  QObject::connect(&singleObject, &Object::signal0, &singleObject, &Object::slot0);
132  } else {
133  singleObject.connect(&singleObject, SIGNAL(signal0()), SLOT(slot0()));
134  }
135 
136  multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(slot0()));
137  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal1()));
138  multiObject.connect(&multiObject, SIGNAL(signal1()), SLOT(slot1()));
139  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal2()));
140  multiObject.connect(&multiObject, SIGNAL(signal2()), SLOT(slot2()));
141  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal3()));
142  multiObject.connect(&multiObject, SIGNAL(signal3()), SLOT(slot3()));
143  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal4()));
144  multiObject.connect(&multiObject, SIGNAL(signal4()), SLOT(slot4()));
145  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal5()));
146  multiObject.connect(&multiObject, SIGNAL(signal5()), SLOT(slot5()));
147  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal6()));
148  multiObject.connect(&multiObject, SIGNAL(signal6()), SLOT(slot6()));
149  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal7()));
150  multiObject.connect(&multiObject, SIGNAL(signal7()), SLOT(slot7()));
151  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal8()));
152  multiObject.connect(&multiObject, SIGNAL(signal8()), SLOT(slot8()));
153  // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal9()));
154  multiObject.connect(&multiObject, SIGNAL(signal9()), SLOT(slot9()));
155 
156  if (type == 0) {
157  QBENCHMARK {
158  singleObject.slot0();
159  }
160  } else if (type == 1) {
161  QBENCHMARK {
162  singleObject.emitSignal0();
163  }
164  } else if (type == 2) {
165  QBENCHMARK {
166  multiObject.emitSignal0();
167  }
168  } else if (type == 3) {
169  QBENCHMARK {
170  singleObject.emitSignal1();
171  }
172  } else if (type == 4 || type == 5) {
173  QBENCHMARK {
174  singleObject.emitSignal0();
175  }
176  }
177 }
178 
179 void tst_QObject::signal_many_receivers_data()
180 {
181  QTest::addColumn<int>("receiverCount");
182  QTest::newRow("100 receivers") << 100;
183  QTest::newRow("1 000 receivers") << 1000;
184  QTest::newRow("10 000 receivers") << 10000;
185 }
186 
187 void tst_QObject::signal_many_receivers()
188 {
189  QFETCH(int, receiverCount);
190  Object sender;
191  std::vector<Object> receivers(receiverCount);
192 
193  for (Object &receiver : receivers)
195 
196  QBENCHMARK {
197  sender.emitSignal0();
198  }
199 }
200 
201 void tst_QObject::qproperty_benchmark_data()
202 {
203  QTest::addColumn<QByteArray>("name");
204  const QMetaObject *mo = &QTreeView::staticMetaObject;
205  for (int i = 0; i < mo->propertyCount(); ++i) {
206  QMetaProperty prop = mo->property(i);
207  if (prop.isWritable())
208  QTest::newRow(prop.name()) << QByteArray(prop.name());
209  }
210 }
211 
212 void tst_QObject::qproperty_benchmark()
213 {
215  const char *p = name.constData();
216  QTreeView obj;
217  QVariant v = obj.property(p);
218  QBENCHMARK {
219  obj.setProperty(p, v);
220  (void)obj.property(p);
221  }
222 }
223 
224 void tst_QObject::dynamic_property_benchmark()
225 {
226  QTreeView obj;
227  QBENCHMARK {
228  obj.setProperty("myProperty", 123);
229  (void)obj.property("myProperty");
230  obj.setProperty("myOtherProperty", 123);
231  (void)obj.property("myOtherProperty");
232  }
233 }
234 
235 void tst_QObject::connect_disconnect_benchmark_data()
236 {
237  QTest::addColumn<int>("type");
238  QTest::newRow("normalized signature") << 0;
239  QTest::newRow("unormalized signature") << 1;
240  QTest::newRow("function pointer") << 2;
241  QTest::newRow("normalized signature/handle") << 3;
242  QTest::newRow("unormalized signature/handle") << 4;
243  QTest::newRow("function pointer/handle") << 5;
244  QTest::newRow("functor/handle") << 6;}
245 
246 void tst_QObject::connect_disconnect_benchmark()
247 {
248  QFETCH(int, type);
249  switch (type) {
250  case 0: {
251  QTreeView obj;
252  QBENCHMARK {
253  QObject::connect (&obj, SIGNAL(viewportEntered()), &obj, SLOT(expandAll()));
254  QObject::disconnect(&obj, SIGNAL(viewportEntered()), &obj, SLOT(expandAll()));
255  }
256  } break;
257  case 1: {
258  QTreeView obj;
259  QBENCHMARK {
260  QObject::connect (&obj, SIGNAL(viewportEntered( )), &obj, SLOT(expandAll( ))); // sic: non-normalised
261  QObject::disconnect(&obj, SIGNAL(viewportEntered( )), &obj, SLOT(expandAll( ))); // sic: non-normalised
262  }
263  } break;
264  case 2: {
265  QTreeView obj;
266  QBENCHMARK {
269  }
270  } break;
271  case 3: {
272  QTreeView obj;
273  QBENCHMARK {
274  QObject::disconnect(QObject::connect(&obj, SIGNAL(viewportEntered()), &obj, SLOT(expandAll())));
275  }
276  } break;
277  case 4: {
278  QTreeView obj;
279  QBENCHMARK {
280  QObject::disconnect(QObject::connect(&obj, SIGNAL(viewportEntered( )), &obj, SLOT(expandAll( )))); // sic: non-normalised
281  }
282  } break;
283  case 5: {
284  QTreeView obj;
285  QBENCHMARK {
287  }
288  } break;
289  case 6: {
290  QTreeView obj;
291  Functor functor;
292  QBENCHMARK {
294  }
295  } break;
296  }
297 }
298 
299 void tst_QObject::receiver_destroyed_benchmark()
300 {
301  Object sender;
302  QBENCHMARK {
303  Object receiver;
305  }
306 }
307 
309 
310 #include "tst_bench_qobject.moc"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
Definition: main.cpp:55
void emitSignal0()
Definition: object.cpp:30
void slot0()
Definition: object.cpp:36
void emitSignal1()
Definition: object.cpp:32
void signal0()
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
The QMetaProperty class provides meta-data about a property.
Definition: qmetaobject.h:277
bool isWritable() const
const char * name() const
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
QObject * sender() const
Definition: qobject.cpp:2472
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Definition: qobject.cpp:3048
void setObjectName(const QString &name)
Definition: qobject.cpp:1261
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
The QTreeView class provides a default model/view implementation of a tree view.
Definition: qtreeview.h:56
void expandAll()
Definition: qtreeview.cpp:2698
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
auto mo
[7]
void slot3(const QString &a, const QString &b, const QString &c)
void slot1(const QString &a)
void slot4(const QString &a, const QString &b, const QString &c, const QString &d)
void slot5(const QString &a, const QString &b, const QString &c, const QString &d, const QString &e)
void slot2(const QString &a, const QString &b)
void slot6(const QString &a, const QString &b, const QString &c, const QString &d, const QString &e, const QString &f)
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
void
Definition: png.h:1080
#define QBENCHMARK
Definition: qbenchmark.h:76
#define QBENCHMARK_ONCE
Definition: qbenchmark.h:80
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
GLenum type
Definition: qopengl.h:270
GLsizei const GLfloat * v
[13]
GLenum GLenum GLsizei count
GLuint name
GLhandleARB obj
[2]
Definition: qopenglext.h:4164
GLboolean reset
Definition: qopenglext.h:2748
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:165
Definition: main.cpp:38
void allocator()
@ SignalsAndSlotsBenchmarkConstant
@ CreationDeletionBenckmarkConstant