src/testlib/qbenchmark.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtTest module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "QtTest/qbenchmark.h"
       
    43 #include "QtTest/private/qbenchmark_p.h"
       
    44 
       
    45 #ifdef QT_GUI_LIB
       
    46 #include <QtGui/qapplication.h>
       
    47 #endif
       
    48 
       
    49 #include <QtCore/qprocess.h>
       
    50 #include <QtCore/qdir.h>
       
    51 #include <QtCore/qset.h>
       
    52 #include <QtCore/qdebug.h>
       
    53 
       
    54 QT_BEGIN_NAMESPACE
       
    55 
       
    56 QBenchmarkGlobalData *QBenchmarkGlobalData::current;
       
    57 
       
    58 QBenchmarkGlobalData::QBenchmarkGlobalData()
       
    59     : measurer(0)
       
    60     , walltimeMinimum(-1)
       
    61     , iterationCount(-1)
       
    62     , medianIterationCount(-1)
       
    63     , createChart(false)
       
    64     , verboseOutput(false)
       
    65     , mode_(WallTime)
       
    66 {
       
    67     setMode(mode_);
       
    68 }
       
    69 
       
    70 QBenchmarkGlobalData::~QBenchmarkGlobalData()
       
    71 {
       
    72     delete measurer;
       
    73     QBenchmarkGlobalData::current = 0;
       
    74 }
       
    75 
       
    76 void QBenchmarkGlobalData::setMode(Mode mode)
       
    77 {
       
    78     mode_ = mode;
       
    79 
       
    80     if (measurer)
       
    81         delete measurer;
       
    82     measurer = createMeasurer();
       
    83 }
       
    84 
       
    85 QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer()
       
    86 {
       
    87     QBenchmarkMeasurerBase *measurer = 0;
       
    88     if (0) {
       
    89 #ifdef QTESTLIB_USE_VALGRIND
       
    90     } else if (mode_ == CallgrindChildProcess || mode_ == CallgrindParentProcess) {
       
    91         measurer = new QBenchmarkCallgrindMeasurer;
       
    92 #endif
       
    93 #ifdef HAVE_TICK_COUNTER
       
    94     } else if (mode_ == TickCounter) {
       
    95         measurer = new QBenchmarkTickMeasurer;
       
    96 #endif
       
    97     } else if (mode_ == EventCounter) {
       
    98         measurer = new QBenchmarkEvent;
       
    99     } else {
       
   100         measurer =  new QBenchmarkTimeMeasurer;
       
   101     }
       
   102     measurer->init();
       
   103     return measurer;
       
   104 }
       
   105 
       
   106 int QBenchmarkGlobalData::adjustMedianIterationCount()
       
   107 {
       
   108     if (medianIterationCount != -1) {
       
   109         return medianIterationCount;
       
   110     } else {
       
   111         return measurer->adjustMedianCount(1);
       
   112     }
       
   113 }
       
   114 
       
   115 
       
   116 QBenchmarkTestMethodData *QBenchmarkTestMethodData::current;
       
   117 
       
   118 QBenchmarkTestMethodData::QBenchmarkTestMethodData()
       
   119 :resultAccepted(false), runOnce(false), iterationCount(-1)
       
   120 {
       
   121    
       
   122 }
       
   123 
       
   124 QBenchmarkTestMethodData::~QBenchmarkTestMethodData()
       
   125 {
       
   126     QBenchmarkTestMethodData::current = 0;
       
   127 }
       
   128 
       
   129 void QBenchmarkTestMethodData::beginDataRun()
       
   130 {
       
   131     iterationCount = adjustIterationCount(1);
       
   132 }
       
   133 
       
   134 void QBenchmarkTestMethodData::endDataRun()
       
   135 {
       
   136 
       
   137 }
       
   138 
       
   139 int QBenchmarkTestMethodData::adjustIterationCount(int suggestion)
       
   140 {
       
   141     // Let the -iteration-count option override the measurer.
       
   142     if (QBenchmarkGlobalData::current->iterationCount != -1) {
       
   143         iterationCount = QBenchmarkGlobalData::current->iterationCount;
       
   144     } else {
       
   145         iterationCount = QBenchmarkGlobalData::current->measurer->adjustIterationCount(suggestion);
       
   146     }
       
   147 
       
   148     return iterationCount;
       
   149 }
       
   150 
       
   151 void QBenchmarkTestMethodData::setResult(qint64 value)
       
   152 {
       
   153     bool accepted = false;
       
   154 
       
   155     // Always accept the result if the iteration count has been
       
   156     // specified on the command line with -iteartion-count.
       
   157     if (QBenchmarkGlobalData::current->iterationCount != -1)
       
   158         accepted = true;
       
   159 
       
   160     if (QBenchmarkTestMethodData::current->runOnce) {
       
   161         iterationCount = 1;
       
   162         accepted = true;
       
   163     }
       
   164     
       
   165     // Test the result directly without calling the measurer if the minimum time 
       
   166     // has been specifed on the command line with -minimumvalue.
       
   167     else if (QBenchmarkGlobalData::current->walltimeMinimum != -1)
       
   168         accepted = (value > QBenchmarkGlobalData::current->walltimeMinimum);
       
   169     else
       
   170         accepted = QBenchmarkGlobalData::current->measurer->isMeasurementAccepted(value);
       
   171 
       
   172     // Accept the result or double the number of iterations.
       
   173     if (accepted)
       
   174         resultAccepted = true;
       
   175     else
       
   176         iterationCount *= 2;
       
   177 
       
   178     this->result = 
       
   179         QBenchmarkResult(QBenchmarkGlobalData::current->context, value, iterationCount);
       
   180 }
       
   181 
       
   182 /*!
       
   183     \class QTest::QBenchmarkIterationController
       
   184     \internal
       
   185 
       
   186     The QBenchmarkIterationController class is used by the QBENCHMARK macro to
       
   187     drive the benchmarking loop. It is repsonsible for starting and stopping
       
   188     the timing measurements as well as calling the result reporting functions.
       
   189 */
       
   190 
       
   191 /*! \internal
       
   192 */
       
   193 QTest::QBenchmarkIterationController::QBenchmarkIterationController(RunMode runMode)
       
   194 {
       
   195     i = 0;
       
   196     if (runMode == RunOnce)
       
   197         QBenchmarkTestMethodData::current->runOnce = true;    
       
   198     QTest::beginBenchmarkMeasurement();
       
   199 }
       
   200 
       
   201 QTest::QBenchmarkIterationController::QBenchmarkIterationController()
       
   202 {
       
   203     i = 0;
       
   204     QTest::beginBenchmarkMeasurement();
       
   205 }
       
   206 
       
   207 /*! \internal
       
   208 */
       
   209 QTest::QBenchmarkIterationController::~QBenchmarkIterationController()
       
   210 {
       
   211     QBenchmarkTestMethodData::current->setResult(QTest::endBenchmarkMeasurement());
       
   212 }
       
   213 
       
   214 /*! \internal
       
   215 */
       
   216 bool QTest::QBenchmarkIterationController::isDone()
       
   217 {
       
   218     if (QBenchmarkTestMethodData::current->runOnce)
       
   219         return i > 0;
       
   220     return i >= QTest::iterationCount();
       
   221 }
       
   222 
       
   223 /*! \internal
       
   224 */
       
   225 void QTest::QBenchmarkIterationController::next()
       
   226 {
       
   227     ++i;
       
   228 }
       
   229 
       
   230 /*! \internal
       
   231 */
       
   232 int QTest::iterationCount()
       
   233 {
       
   234     return QBenchmarkTestMethodData::current->iterationCount;
       
   235 }
       
   236 
       
   237 /*! \internal
       
   238 */
       
   239 void QTest::setIterationCountHint(int count)
       
   240 {
       
   241     QBenchmarkTestMethodData::current->adjustIterationCount(count);
       
   242 }
       
   243 
       
   244 /*! \internal
       
   245 */
       
   246 void QTest::setIterationCount(int count)
       
   247 {
       
   248     QBenchmarkTestMethodData::current->iterationCount = count;
       
   249     QBenchmarkTestMethodData::current->resultAccepted = true;
       
   250 }
       
   251 
       
   252 /*! \internal
       
   253 */
       
   254 void QTest::beginBenchmarkMeasurement()
       
   255 {
       
   256     QBenchmarkGlobalData::current->measurer->start();
       
   257     // the clock is ticking after the line above, don't add code here.
       
   258 }
       
   259 
       
   260 /*! \internal
       
   261 */
       
   262 qint64 QTest::endBenchmarkMeasurement()
       
   263 {
       
   264     // the clock is ticking before the line below, don't add code here.
       
   265     return QBenchmarkGlobalData::current->measurer->stop();    
       
   266 }
       
   267 
       
   268 /*! \internal
       
   269 */
       
   270 void QTest::setResult(qint64 result)
       
   271 {
       
   272     QBenchmarkTestMethodData::current->setResult(result);
       
   273 }
       
   274 
       
   275 /*! \internal
       
   276 */
       
   277 void QTest::setResult(const QString &tag, qint64 result)
       
   278 {
       
   279     QBenchmarkContext context = QBenchmarkGlobalData::current->context;
       
   280     context.tag = tag;
       
   281     QBenchmarkTestMethodData::current->result = 
       
   282         QBenchmarkResult( context, result,
       
   283             QBenchmarkTestMethodData::current->iterationCount);
       
   284 }
       
   285 
       
   286 template <typename T>
       
   287 Q_TYPENAME T::value_type qAverage(const T &container)
       
   288 {
       
   289     Q_TYPENAME T::const_iterator it = container.constBegin();
       
   290     Q_TYPENAME T::const_iterator end = container.constEnd();
       
   291     Q_TYPENAME T::value_type acc = Q_TYPENAME T::value_type();
       
   292     int count = 0;
       
   293     while (it != end) {
       
   294         acc += *it;
       
   295         ++it;
       
   296         ++count;
       
   297     }
       
   298     return acc / count;
       
   299 }
       
   300 
       
   301 
       
   302 QT_END_NAMESPACE
       
   303