qt5base-lts/tests/benchmarks
Edward Welbourne 150c6fb74b Add testlib selftests for double and for non-finite float and double
Tidied up the existing float tests in the process.
(In particular, s/SUCCESS/PASS/ since that matches real test output.)
These verify that QCOMPARE() handles floats and doubles as intended.
Extended the existing qFuzzyCompare tests to probe the boundaries of
the ranges of values of both types, in the process.

Revised the toString<double> that qCompare() uses to give enough
precision to actually show some of the differences being tested there
(12 digits, to match what qFuzzyCompare tests, so as to show different
values rather than, e.g. 1e12 for both expected and actual) and to
give consistent results for infinities and NaN (MinGW had eccentric
versions for these, leading to different output from tests, which thus
failed); did the latter also for toString<float> and fixed stray zeros
in MinGW's exponents (which made a kludge in tst_selftest.cpp
redundant, so I removed that, too).

That's further complicated handling of floating-point types, so let's
just keep an eye on how expensive that's getting by adding a benchmark
test for QTest::toString().  Unfortunately, default settings only get
runs that take modest numbers of milliseconds (some as low as 40)
while increasing this with -minumumvalue 100 or more gets the process
killed - and I'm unable to find out who's doing the killing (it's not
QProcess::kill, ::kill or the QtTest WatchDog, as far as I can tell).
So results are rather noisy; the integral tests exhibit speed-ups by
factors up to 5, and slow-downs by factors up to 100, between runs
with and without this change, which does not affec the integral tests.
The relatively modest slow-downs and speed-ups in the floating point
tests thus seem likely to be happenstance rather than signal.

Change-Id: I4a6bbbab6a43bf14a4089e96238a7c8da2c3127e
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
2019-02-06 10:11:22 +00:00
..
corelib Merge remote-tracking branch 'origin/5.11' into dev 2018-07-02 11:23:45 +02:00
dbus Use dependencies instead of CONFIG+=ordered 2017-12-02 11:09:15 +00:00
gui Implement support for 16bpc image formats 2018-08-11 14:12:48 +00:00
network Benchmarks: tst_tcpserver: Remove unnecessary qprocess include 2018-02-05 07:16:01 +00:00
opengl Updated license headers 2016-01-21 18:55:18 +00:00
plugins/imageformats/jpeg Updated license headers 2016-01-21 18:55:18 +00:00
sql psql: do not try to get table name when PQftable returns InvalidOid 2018-02-22 19:00:08 +00:00
testlib Add testlib selftests for double and for non-finite float and double 2019-02-06 10:11:22 +00:00
widgets Benchmarks/QGraphicsView: re-enable graphicslayout/graphicslinearlayout 2018-04-04 06:54:39 +00:00
benchmarks.pro Add testlib selftests for double and for non-finite float and double 2019-02-06 10:11:22 +00:00
README Whitespace cleanup: remove trailing whitespace 2013-03-16 20:22:50 +01:00
trusted-benchmarks.pri Initial import from the monolithic Qt. 2011-04-27 12:05:43 +02:00

The most reliable way of running benchmarks is to do it in an otherwise idle
system. On a busy system, the results will vary according to the other tasks
demanding attention in the system.

We have managed to obtain quite reliable results by doing the following on
Linux (and you need root):

 - switching the scheduler to a Real-Time mode
 - setting the processor affinity to one single processor
 - disabling the other thread of the same core

This should work rather well for CPU-intensive tasks. A task that is in Real-
Time mode will simply not be preempted by the OS. But if you make OS syscalls,
especially I/O ones, your task will be de-scheduled. Note that this includes
page faults, so if you can, make sure your benchmark's warmup code paths touch
most of the data.

To do this you need a tool called schedtool (package schedtool), from
http://freequaos.host.sk/schedtool/

From this point on, we are using CPU0 for all tasks:

If you have a Hyperthreaded multi-core processor (Core-i5 and Core-i7), you
have to disable the other thread of the same core as CPU0. To discover which
one it is:

$ cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list

This will print something like 0,4, meaning that CPUs 0 and 4 are sibling
threads on the same core. So we'll turn CPU 4 off:

(as root)
# echo 0 > /sys/devices/system/cpu/cpu4/online

To turn it back on, echo 1 into the same file.

To run a task on CPU 0 exclusively, using FIFO RT priority 10, you run the
following:

(as root)
# schedtool -F -p 10 -a 1 -e ./taskname

For example:
# schedtool -F -p 10 -a 1 -e ./tst_bench_qstring -tickcounter

Warning: if your task livelocks or takes far too long to complete, your system
may be unusable for a long time, especially if you don't have other cores to
run stuff on. To prevent that, run it before schedtool and time it.

You can also limit the CPU time that the task is allowed to take. Run in the
same shell as you'll run schedtool:

$ ulimit -s 300
To limit to 300 seconds (5 minutes)

If your task runs away, it will get a SIGXCPU after consuming 5 minutes of CPU
time (5 minutes running at 100%).

If your app is multithreaded, you may want to give it more CPUs, like CPU0 and
CPU1 with -a 3  (it's a bitmask).

For best results, you should disable ALL other cores and threads of the same
processor. The new Core-i7 have one processor with 4 cores,
each core can run 2 threads; the older Mac Pros have two processors with 4
cores each. So on those Mac Pros, you'd disable cores 1, 2 and 3, while on the
Core-i7, you'll need to disable all other CPUs.

However, disabling just the sibling thread seems to produce very reliable
results for me already, with variance often below 0.5% (even though there are
some measurable spikes).

Other things to try:

Running the benchmark with highest priority, i.e. "sudo nice -19"
usually produces stable results on some machines. If the benchmark also
involves displaying something on the screen (on X11), running it with
"-sync" is a must. Though, in that case the "real" cost is not correct,
but it is useful to discover regressions.

Also; not many people know about ionice (1)
      ionice - get/set program io scheduling class and priority