]> git.tdb.fi Git - ext/sigc++-2.0.git/blob - docs/website/benchmark.shtml
Import libsigc++ 2.10.8 sources
[ext/sigc++-2.0.git] / docs / website / benchmark.shtml
1 <!-- SSI fragments/htm_declaration.html_fragment begin -->
2 <!--#include virtual="fragments/html_declaration.html_fragment" -->
3 <!-- SSI fragments/html_declaration.html_fragment end -->
4
5
6 <h3>Signal System Comparison: Qt (tm) vs Libsigc++</h3><p>
7
8 <a name="preface"><h3>Preface</h3></a>
9
10 This comparison is by no means a fair fight.  Libsigc++ can't possibly lose
11 and will defeat Qt soundly.  First of all, Qt and Libsigc++ have different
12 design goals and thus the things measured to show the features of Libsigc++,
13 may not be considerations for Qt.  a excellent widget set and a program
14 framework while libsigc++ is nothing more that a small component.  Speed of
15 signal/slot operations is not a very big consideration in most GUI code.
16 Further, Qt was written several years ago, while I still have cuts in my
17 fingers from feeling the bleeding edge.  I am controlling the conditions of
18 the tests, and thus when I find a failing in libsigc++ during the testing, I
19 get to go back and fix it.  On the other hand, TrollTech is concerned with
20 binary compatiblity with old versions. Further, libsigc++ is a template
21 library meaning all the code is specialized for each usage.  On the other
22 hand, Qt is a generalist using strings to store all signal information.
23 This is flexible but slower. 
24
25 <p>
26 That said there is a basis for comparison.  Both libsigc++ and Qt provide
27 similar functionality with their signal/slot system.  They both are C++
28 libraries which run under both windows and Unix.  Both originated from
29 widget sets and both have flexiblity and ease of use a key factors.   Qt
30 version 1.42 was used and Libsigc++ modified from version 0.8.0.
31 <p>
32
33 (Note that I have been in contact with Arnt Gulbrandsen of Troll Tech AS.
34 He has discovered a problem in the Qt system than resulted in excessive time
35 in the emit functions.  He indicates that it should be fixed for Qt 2.0
36 which will improve their performance.) 
37
38 <p>
39 <a name="arch"><h3>String based verse Templates</h3></a>
40
41 There is a significant differences between the architectures of Libsigc++
42 and Qt signal system.  Libsigc++ is a template based while Qt is string
43 based.  
44 <P>
45
46 String based signal systems have a number of advantages and disadvantages
47 over template based.  It is simpler to implement, so it should in general
48 win in size and compile speed compared to the bloat of templates.  As they
49 don't need anything but basic C++ features, such systems are more portable
50 accross systems.  Any signal you want can be declared, including new signals
51 at runtime.  (Although Qt doesn't take advantage of this.)  This is also a
52 disadvantage for the approach as the compiler does not check the typesafty
53 of connections until they are called at runtime.  Some basic checking may be
54 done, but in general it is minimal.  Often this approach requires a
55 preprocessor to hide the string nature and do such checking. 
56 <p>
57
58 Template based on the other hand is entirely different beast.  Everything is
59 compiled in to the binary including the connections forming agents.  This is
60 a huge advantage that whatever compiles, runs.  Beter still no precompiler
61 was needed, as the whole system can be build using C++ notation.  All
62 typechecking is done at compile time by the compiler, thus no checking needs
63 to be performed during the runtime operations.  Faster running does come a
64 price.  All the templates generate code which will appear in the binary.
65 Therefore great pains in the design of a template library are taken to hold
66 this to a minumum.  Further, the template capablities of different compilers
67 vary wildly, so portablity is hard to achieve.  These are not insurmountable
68 though, as libsigc++ has excellent portablity and size.  <p>
69
70
71 <a name="features"><h3>Table of Features</h3></a>
72
73 The following features are relevant when comparing Qt signal/slot system
74 and Libsigc++.
75
76 <table width="90%" border="1">
77 <tr><td> Feature        </td><td> Qt </td><td> Libsigc++ </td></tr>
78 <tr><td> Requires no special compiler steps     </td><td> No    </td><td> Yes  </td></tr>
79 <tr><td> Protected Signals              </td><td> Yes   </td><td> Yes  </td></tr>
80 <tr><td> Public Signals                 </td><td> No    </td><td> Yes  </td></tr>
81 <tr><td> Any function can be slot       </td><td> No    </td><td> Yes  </td></tr>
82 <tr><td> Void returns                   </td><td> Yes   </td><td> Yes  </td></tr>
83 <tr><td> Non-void returns               </td><td> No    </td><td> Yes  </td></tr>
84 <tr><td> Reference returns              </td><td> No    </td><td> No   </td></tr>
85 <tr><td> Any type in argument list      </td><td> No    </td><td> Yes  </td></tr>
86 <tr><td> Signals in global scope        </td><td> No    </td><td> Yes  </td></tr>
87 <tr><td> Signals in class scope         </td><td> Yes   </td><td> Yes  </td></tr>
88 <tr><td> Signals in other scopes        </td><td> No    </td><td> Yes  </td></tr>
89 <tr><td> Bindable arguments             </td><td> No    </td><td> Yes  </td></tr>
90 <tr><td> Argument type conversion       </td><td> No    </td><td> Yes  </td></tr>
91 <tr><td> Return type conversion         </td><td> No    </td><td> Yes  </td></tr>
92 <tr><td> Namespace support              </td><td> No    </td><td> Yes  </td></tr>
93 <tr><td> Signal Cost (bytes)            </td><td> 0     </td><td> 4    </td></tr>
94 </table>
95 <p>
96
97 <a name="details"><h3>Feature Details</h3></a>
98 Preprocessors and such generally indicate a lack of faith in the compiler
99 and add an extra step in compilation.  Qt does this because of its support
100 for early compilers with poor template support.  At this time, such things
101 aren't generally required.
102 <p>
103
104 Public and protected refer to the access of a signal in a class.  Qt can
105 only emit from inside the owning class.  Libsigc++ signals are normal
106 objects and thus can be private, protected or public.
107 <p>
108
109 Void and non-void returns refer to what type a signal may return from emit.
110 Qt only supports void returns.  Libsigc++ supports return types of most
111 kinds including building lists of return values.  However, pass by reference
112 still has a few bugs.
113 <p>
114
115 There can be some restriction on the number and type of arguments a signal
116 can take.  Qt does not support templates or function pointers in argument
117 lists.  This can be gotten arround with careful typedefs.  This is a result
118 of the moc preprocessor.
119 <p>
120
121 Signal declarations may have restrictions in the location of declaration.
122 Libsigc++ signals can be declared anywhere including within templates and
123 nested classes.  This a big plus.
124 <p>
125
126 Libsigc++ supplies a set of adaptors for altering the types of slots
127 including binding arguments and converting types.  This is a feature that
128 grew out of necessity of the gtkmm project needing to take something from a
129 C type to a C++ type.  It can be very useful.
130 <p>
131
132 Size of signals is the one place where Qt is a clear winner.  Zero is a very
133 attractive cost.  The same effect can be achieved using libsigc++ with a
134 specialized signal and a map.  However, this arrangement would be slower.
135 This functionality is scheduled to be added to libsigc++.
136 <p>
137
138 <a name="speed"><h3>Speed benchmarks</h3></a>
139
140 To measure the speed of both systems, an emit was placed in a tight loop.
141 The emit called a trivial function.  The benchmark speed was taken to be the
142 total elapsed time as measured by unix "time" minus time for the same
143 program to run calling directly divided by the number of calls.  Iterations
144 were chosen to ensure the system ran for at least 20 seconds.  Both were
145 dynamically linked, stripped, and fully optimized (-03).  Dynamic linked was
146 tested to have insignificant effects. The benchmarking machine was a
147 sluggish 133Mhz 586.
148 <p>
149 The number of slots was varied to determine how much of the cost is per emit
150 and how much is per slot attached.
151 <p>
152
153 Libsigc++ could be run with either thread safe marshalling of the return
154 value, skipping the return value or marshalling in a non-thread safe manner.
155 The closest comparison between Qt and libsigc++ is to skip the return value,
156 because Qt has no support for return types. 
157
158 <pre>
159 libsigc++ without marshal
160 =====================================================
161 iterations: 2^26
162
163       0 base  0 emit  1 base  1 emit  2 base  2 emit
164       1.023   10.58   2.03    32.717  2.533   56.237
165
166 O penalty:   140ns
167 1 penalty:   460ns
168 2 penalty:   800ns
169
170 Emit cost:   140ns
171 Slot cost:   330ns
172
173
174 libsigc++ with marshal
175 =====================================================
176 iterations: 2^24
177
178       0 base  0 emit  1 base  1 emit  2 base  2 emit
179       0.27    2.93    0.52    24.04   0.65    45.48
180
181 0 penalty:   160ns
182 1 penalty:  1400ns
183 2 penalty:  2670ns
184
185 Emit cost:   160ns
186 Slot cost:  1260ns
187
188
189 Qt
190 =====================================================
191 iterations: 2^21  (0 done a 2^24 for better resolution)
192
193       0 base  0 emit  1 base  1 emit  2 base  2 emit
194       0.37     5.28   0.18    32.34   0.20    34.25
195       0.37    31.82
196
197 0 penalty:  1870ns (295ns shortcut)
198 1 penalty: 15300ns
199 2 penalty: 16200ns
200
201 Emit cost: 1800ns-15300ns 
202   (varies with number of signals/slot attached.)
203 Slot cost:   900ns
204
205 </pre>
206 Because Qt shares a data structure for all signal lists,
207 the times for an emit are hard to calculate.  In general
208 the more signals connected the longer it took to find the
209 data needed to emit the slot, increasing the emit cost.
210 As very small numbers of connects were tested, it is not
211 clear how high this cost can go.  (Libsigc++ is
212 more direct in approach, so one can calculate purely
213 by multiplying up the frequencies by the costs.)
214 <p>
215
216 Qt does a short cut for emitting signals when no connections
217 have been established yet
218 which gives a massive speed up to emit time.  However,
219 as the general case will have at least one signal connected
220 somewhere in the object, this is not representative.
221 If there is at least one slot connected to the signal, a 15ms
222 time delay is paid.  This would be a good area in Qt for improvement.
223 <p>
224
225 In a direct comparison, libsigc++ is 30 times faster for emiting
226 one connected signal.  Thread safe
227 marshalling of the return values increase emit penalty by 3, which
228 still is a order of magnitude faster that Qt for emitting a 
229 signal with one slot.  The per slot cost of without marshalling of
230 return values is only 3 times slowing in Qt then libsigc++, and
231 comparable with the marshaller.  However, the initial startup
232 cost dominates over all others.  So as far as speed is concerned,
233 libsigc++ is clearly better. 
234 <p>
235
236 <a name="size"><h3>Binary size</h3></a>
237
238 To show that libsigc++ is not taking advantage of its templates to
239 specialize every detail at the cost of a huge binary, the size of the
240 benchmarking programs was compared.  Both were striped and dynamically
241 linked.
242
243 <pre>
244 Libsigc++:  5456 bytes
245 Qt:         6020 bytes
246 </pre>
247
248 The binary sizes are comparable with a slight edge to libsigc++.  As the
249 programs are very small, it should not be assumed that this trend holds as
250 number of signals increases.
251 <p>
252
253 <a name="compile"><h3>Compile time</h3></a>
254
255 Another major concern with Libsigc++ is that its hundreds of templates are
256 likely going to take most compilers to its knees.  This is a very valid
257 concern.  So I measured the time of compiling the benchmark programs
258
259 <pre>
260 Libsigc++: 0:02.62
261 Qt:        0:03.09
262 </pre>
263
264 Again, there is a slight edge to Libsigc++.  This at least means that
265 libsigc++ is not completely out of the ballpark at slow compiles.  Again one
266 should not assume this holds for very large programs.
267 <p>
268
269 <a name="analysis"><h3>Final Analysis</h3></a>
270
271 As expected libsigc++ beat Qt's signal system hands down.  It was an order
272 of magnitude faster with no significant cost to binary size and compile
273 time.  It is slightly larger on the size of objects which may be a concern
274 if hundreds of signals are used.  An excellent start for a free library!
275
276 <P>
277 <a name="references"><h3>References</h3></a>
278
279 <ul>
280  <li><a href="http://www.troll.no/qt/metaobjects.html">Signals, Slots and the Meta Object Compiler</a></li>
281  <li><a href="http://www.troll.no/qt/moc.html">Using the Meta Object Compiler</a></li>
282 </ul>
283 <p>
284 tm - Qt is a trademark of Troll Tech As of Norway. 
285
286
287
288 <!-- SSI fragments/footer.html_fragment begin -->
289 <!--#include virtual="fragments/footer.html_fragment" -->
290 <!-- SSI fragments/footer.html_fragment begin -->