第5章:编写基准测试

 Qt Test
时间:

如何编写基准测试。

在最后一章,我们将演示如何使用Qt测试编写基准测试。

基准测试

为了创建基准测试,我们使用QBENCHMARK宏扩展了测试函数。基准测试函数通常由设置代码和QBENCHMARK宏组成,该宏包含要测量的代码。这个测试函数对QString::localeAwareCompare()进行基准测试。

// benchmarking.cpp
#include <QtWidgets>
#include <qtest.h>

class TestBenchmark : public QObject
{
    Q_OBJECT

private slots:
    void simple();
    void multiple_data();
    void multiple();
    void series_data();
    void series();


};

void TestBenchmark::simple()
{
    QString str1 = QLatin1String("This is a test string");
    QString str2 = QLatin1String("This is a test string");

    QCOMPARE(str1.localeAwareCompare(str2), 0);

    QBENCHMARK {
        str1.localeAwareCompare(str2);
    }
}

void TestBenchmark::multiple_data()
{
    QTest::addColumn<bool>("useLocaleCompare");
    QTest::newRow("locale aware compare") << true;
    QTest::newRow("standard compare") << false;
}

void TestBenchmark::multiple()
{
    QFETCH(bool, useLocaleCompare);
    QString str1 = QLatin1String("This is a test string");
    QString str2 = QLatin1String("This is a test string");

    int result;
    if(useLocaleCompare)
    {
        QBENCHMARK {
            result = str1.localeAwareCompare(str2);
        }
    } else {
        QBENCHMARK {
            result = (str1 == str2);
        }
    }

    Q_UNUSED(result);
}

void TestBenchmark::series_data()
{
    QTest::addColumn<bool>("useLocaleCompare");
    QTest::addColumn<int>("stringSize");

    for(int i = 1; i < 10000; i += 2000)
    {
        QByteArray size = QByteArray::number(i);
        QTest::newRow(("locale aware compare--" + size).constData()) << true << i;
        QTest::newRow(("standard compare--" + size).constData()) << false << i;
    }
}

void TestBenchmark::series()
{
    QFETCH(bool, useLocaleCompare);
    QFETCH(int, stringSize);

    QString str1 = QString().fill('A', stringSize);
    QString str2 = QString().fill('A', stringSize);
    int result;
    if(useLocaleCompare) {
        QBENCHMARK {
            result = str1.localeAwareCompare(str2);
        }
    } else {
        QBENCHMARK {
            result = (str1 == str2);
        }
    }

    Q_UNUSED(result);
}


QTEST_MAIN(TestBenchmark)
#include "benchmarking.moc"

解答

void TestBenchmark::simple()
{
    QString str1 = QLatin1String("This is a test string");
    QString str2 = QLatin1String("This is a test string");

    QCOMPARE(str1.localeAwareCompare(str2), 0);

    QBENCHMARK {
        str1.localeAwareCompare(str2);
    }
}

设置可以在函数开始时完成,此时时钟不运行。QBENCHMARK宏中的代码将被测量,为了得到准确的测量结果,可能会重复几次。

有几个后端可用:

  • Walltime
  • CPU tick counter
  • Event Counter
  • Valgrind Callgrind
  • Linux Perf

数据功能

数据函数对于创建比较多个数据输入的基准测试非常有用,例如支持语言环境的比较和标准的比较。

void TestBenchmark::multiple_data()
{
    QTest::addColumn<bool>("useLocaleCompare");
    QTest::newRow("locale aware compare") << true;
    QTest::newRow("standard compare") << false;
}

测试函数然后使用这些数据来确定要进行基准测试的内容。

void TestBenchmark::multiple()
{
    QFETCH(bool, useLocaleCompare);
    QString str1 = QLatin1String("This is a test string");
    QString str2 = QLatin1String("This is a test string");

    int result;
    if(useLocaleCompare)
    {
        QBENCHMARK {
            result = str1.localeAwareCompare(str2);
        }
    } else {
        QBENCHMARK {
            result = (str1 == str2);
        }
    }

    Q_UNUSED(result);
}

“if (useLocaleCompare)”开关被放置在QBENCHMARK宏之外,以避免测量其开销。每个基准测试函数可以有一个活动的QBENCHMARK宏。

测试模拟数据

********* Start testing of TestBenchmark *********
Config: Using QtTest library 5.14.0, Qt 5.14.0 (i386-little_endian-ilp32 shared (dynamic) debug build; by MSVC 2017)
PASS   : TestBenchmark::initTestCase()
PASS   : TestBenchmark::simple()
RESULT : TestBenchmark::simple():
     0.0021 msecs per iteration (total: 70, iterations: 32768)
PASS   : TestBenchmark::multiple(locale aware compare)
RESULT : TestBenchmark::multiple():"locale aware compare":
     0.0014 msecs per iteration (total: 94, iterations: 65536)
PASS   : TestBenchmark::multiple(standard compare)
RESULT : TestBenchmark::multiple():"standard compare":
     0.00010 msecs per iteration (total: 54, iterations: 524288)
PASS   : TestBenchmark::series(locale aware compare--1)
RESULT : TestBenchmark::series():"locale aware compare--1":
     0.0011 msecs per iteration (total: 76, iterations: 65536)
PASS   : TestBenchmark::series(standard compare--1)
RESULT : TestBenchmark::series():"standard compare--1":
     0.000088 msecs per iteration (total: 93, iterations: 1048576)
PASS   : TestBenchmark::series(locale aware compare--2001)
RESULT : TestBenchmark::series():"locale aware compare--2001":
     0.024 msecs per iteration (total: 51, iterations: 2048)
PASS   : TestBenchmark::series(standard compare--2001)
RESULT : TestBenchmark::series():"standard compare--2001":
     0.00094 msecs per iteration (total: 62, iterations: 65536)
PASS   : TestBenchmark::series(locale aware compare--4001)
RESULT : TestBenchmark::series():"locale aware compare--4001":
     0.0493 msecs per iteration (total: 101, iterations: 2048)
PASS   : TestBenchmark::series(standard compare--4001)
RESULT : TestBenchmark::series():"standard compare--4001":
     0.0018 msecs per iteration (total: 60, iterations: 32768)
PASS   : TestBenchmark::series(locale aware compare--6001)
RESULT : TestBenchmark::series():"locale aware compare--6001":
     0.073 msecs per iteration (total: 75, iterations: 1024)
PASS   : TestBenchmark::series(standard compare--6001)
RESULT : TestBenchmark::series():"standard compare--6001":
     0.0027 msecs per iteration (total: 90, iterations: 32768)
PASS   : TestBenchmark::series(locale aware compare--8001)
RESULT : TestBenchmark::series():"locale aware compare--8001":
     0.096 msecs per iteration (total: 99, iterations: 1024)
PASS   : TestBenchmark::series(standard compare--8001)
RESULT : TestBenchmark::series():"standard compare--8001":
     0.0035 msecs per iteration (total: 58, iterations: 16384)
PASS   : TestBenchmark::cleanupTestCase()
Totals: 15 passed, 0 failed, 0 skipped, 0 blacklisted, 3976ms
********* Finished testing of TestBenchmark *********

外部工具

用于处理和可视化测试数据的工具是qtestlib-tools项目的一部分。其中包括用于比较从测试运行中获得的性能数据的工具,以及用于生成基于web的性能数据图的实用程序。

有关这些工具的更多信息和一个简单的图形示例,请参阅qtestlib工具声明。


0 评论