From d115f17cb84f759c2146eaaa25bf52a9d7b900f0 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 5 Jul 2021 18:24:23 +0200 Subject: Rename QFile benchmark's source file to tst_bench_qfile.cpp Let's have fewer files with the same main.cpp name. Change-Id: Iad94478affcca73a25ed29ba4380f1b3ca4f329d Reviewed-by: Volker Hilsheimer --- tests/benchmarks/corelib/io/qfile/CMakeLists.txt | 2 +- tests/benchmarks/corelib/io/qfile/main.cpp | 618 --------------------- .../corelib/io/qfile/tst_bench_qfile.cpp | 618 +++++++++++++++++++++ 3 files changed, 619 insertions(+), 619 deletions(-) delete mode 100644 tests/benchmarks/corelib/io/qfile/main.cpp create mode 100644 tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp (limited to 'tests/benchmarks/corelib/io/qfile') diff --git a/tests/benchmarks/corelib/io/qfile/CMakeLists.txt b/tests/benchmarks/corelib/io/qfile/CMakeLists.txt index 6ae5029a8a..ed14a31780 100644 --- a/tests/benchmarks/corelib/io/qfile/CMakeLists.txt +++ b/tests/benchmarks/corelib/io/qfile/CMakeLists.txt @@ -6,7 +6,7 @@ qt_internal_add_benchmark(tst_bench_qfile SOURCES - main.cpp + tst_bench_qfile.cpp PUBLIC_LIBRARIES Qt::CorePrivate Qt::Test diff --git a/tests/benchmarks/corelib/io/qfile/main.cpp b/tests/benchmarks/corelib/io/qfile/main.cpp deleted file mode 100644 index fbfe753c7c..0000000000 --- a/tests/benchmarks/corelib/io/qfile/main.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include - -#include - -#include - -#include - -#ifdef Q_OS_WIN -# include -#endif - -#if defined(Q_OS_QNX) && defined(open) -#undef open -#endif - -#define BUFSIZE 1024*512 -#define FACTOR 1024*512 -#define TF_SIZE FACTOR*81 - -// 10 predefined (but random() seek positions -// hardcoded to be comparable over several runs -const int seekpos[] = {int(TF_SIZE*0.52), - int(TF_SIZE*0.23), - int(TF_SIZE*0.73), - int(TF_SIZE*0.77), - int(TF_SIZE*0.80), - int(TF_SIZE*0.12), - int(TF_SIZE*0.53), - int(TF_SIZE*0.21), - int(TF_SIZE*0.27), - int(TF_SIZE*0.78)}; - -const int sp_size = sizeof(seekpos)/sizeof(int); - -class tst_qfile: public QObject -{ -Q_ENUMS(BenchmarkType) -Q_OBJECT -public: - enum BenchmarkType { - QFileBenchmark = 1, -#ifdef QT_BUILD_INTERNAL - QFSFileEngineBenchmark, -#endif - Win32Benchmark, - PosixBenchmark, - QFileFromPosixBenchmark - }; -private slots: - void initTestCase(); - - void open_data(); - void open(); - void seek_data(); - void seek(); - - void readSmallFiles_QFile() { readSmallFiles(); } - void readSmallFiles_QFSFileEngine() { readSmallFiles(); } - void readSmallFiles_posix() { readSmallFiles(); } - void readSmallFiles_Win32() { readSmallFiles(); } - - void readSmallFiles_QFile_data(); - void readSmallFiles_QFSFileEngine_data(); - void readSmallFiles_posix_data(); - void readSmallFiles_Win32_data(); - - void readBigFile_QFile_data(); - void readBigFile_QFSFileEngine_data(); - void readBigFile_posix_data(); - void readBigFile_Win32_data(); - - void readBigFile_QFile() { readBigFile(); } - void readBigFile_QFSFileEngine() { readBigFile(); } - void readBigFile_posix() { readBigFile(); } - void readBigFile_Win32() { readBigFile(); } - -private: - void readFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b); - void readBigFile(); - void readSmallFiles(); - - class TestDataDir : public QTemporaryDir - { - void createFile(); - void createSmallFiles(); - public: - TestDataDir() : QTemporaryDir(), fail(errorString().toLocal8Bit()) - { - if (fail.isEmpty() && !QTemporaryDir::isValid()) - fail = "Failed to create temporary directory for data"; - if (isValid()) - createSmallFiles(); - if (isValid()) - createFile(); - if (isValid()) - QTest::qSleep(2000); // let IO settle - } - bool isValid() { return QTemporaryDir::isValid() && fail.isEmpty(); } - QByteArray fail; - QString filename; - } tempDir; -}; - -Q_DECLARE_METATYPE(tst_qfile::BenchmarkType) -Q_DECLARE_METATYPE(QIODevice::OpenMode) -Q_DECLARE_METATYPE(QIODevice::OpenModeFlag) - -/* None of the tests modify the test data in tempDir, so it's OK to only create - * and tear down the directory once. - */ -void tst_qfile::TestDataDir::createFile() -{ - QFile tmpFile(filePath("testFile")); - if (!tmpFile.open(QIODevice::WriteOnly)) { - fail = "Unable to prepare files for test"; - return; - } -#if 0 // Varied data, rather than filling with '\0' bytes: - for (int row = 0; row < FACTOR; ++row) { - tmpFile.write(QByteArray().fill('0' + row % ('0' - 'z'), 80)); - tmpFile.write("\n"); - } -#else - tmpFile.seek(FACTOR * 80); - tmpFile.putChar('\n'); -#endif - filename = tmpFile.fileName(); - tmpFile.close(); -} - -void tst_qfile::TestDataDir::createSmallFiles() -{ - for (int i = 0; i < 1000; ++i) { - QFile f(filePath(QString::number(i))); - if (!f.open(QIODevice::WriteOnly)) { - fail = "Unable to prepare small files for test"; - return; - } - f.seek(511); - f.putChar('\n'); - f.close(); - } -} - -void tst_qfile::initTestCase() -{ - QVERIFY2(tempDir.isValid(), tempDir.fail.constData()); -} - -void tst_qfile::readFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, - QIODevice::OpenModeFlag b) -{ - QTest::addColumn("testType"); - QTest::addColumn("blockSize"); - QTest::addColumn("textMode"); - QTest::addColumn("bufferedMode"); - - QByteArray flagstring; - if (t & QIODevice::Text) - flagstring += "textMode"; - if (b & QIODevice::Unbuffered) { - if (flagstring.size()) - flagstring += ' '; - flagstring += "unbuffered"; - } - if (flagstring.isEmpty()) - flagstring = "none"; - - const int kbs[] = {1, 2, 8, 16, 32, 512}; - for (int kb : kbs) { - const int size = 1024 * kb; - QTest::addRow("BS: %d, Flags: %s", size, flagstring.constData()) - << type << size << t << b; - } -} - -void tst_qfile::readBigFile_QFile_data() -{ - readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); - readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); - readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); - readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); - -} - -void tst_qfile::readBigFile_QFSFileEngine_data() -{ -#ifdef QT_BUILD_INTERNAL - // Support for buffering dropped at 5.10, so only test Unbuffered - readFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); - readFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); -#else - QSKIP("This test requires -developer-build."); -#endif -} - -void tst_qfile::readBigFile_posix_data() -{ - readFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); -} - -void tst_qfile::readBigFile_Win32_data() -{ -#ifdef Q_OS_WIN - readFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); -#else - QSKIP("This is Windows only benchmark."); -#endif -} - -void tst_qfile::readBigFile() -{ - QFETCH(tst_qfile::BenchmarkType, testType); - QFETCH(int, blockSize); - QFETCH(QFile::OpenModeFlag, textMode); - QFETCH(QFile::OpenModeFlag, bufferedMode); - - char buffer[BUFSIZE]; - switch (testType) { - case QFileBenchmark: { - QFile file(tempDir.filename); - file.open(QIODevice::ReadOnly|textMode|bufferedMode); - QBENCHMARK { - while(!file.atEnd()) - file.read(blockSize); - file.reset(); - } - file.close(); - } - break; -#ifdef QT_BUILD_INTERNAL - case QFSFileEngineBenchmark: { - QFSFileEngine fse(tempDir.filename); - fse.open(QIODevice::ReadOnly|textMode|bufferedMode); - QBENCHMARK { - //qWarning() << fse.supportsExtension(QAbstractFileEngine::AtEndExtension); - while (fse.read(buffer, blockSize)) {} - fse.seek(0); - } - fse.close(); - } - break; -#endif - case PosixBenchmark: { - QByteArray data = tempDir.filename.toLocal8Bit(); - const char* cfilename = data.constData(); - FILE* cfile = ::fopen(cfilename, "rb"); - QBENCHMARK { - while(!feof(cfile)) - [[maybe_unused]] auto r = ::fread(buffer, blockSize, 1, cfile); - ::fseek(cfile, 0, SEEK_SET); - } - ::fclose(cfile); - } - break; - case QFileFromPosixBenchmark: { - // No gain in benchmarking this case - } - break; - case Win32Benchmark: { -#ifdef Q_OS_WIN - HANDLE hndl; - - // ensure we don't account string conversion - const wchar_t *cfilename = reinterpret_cast(tempDir.filename.utf16()); - - hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); - Q_ASSERT(hndl); - wchar_t* nativeBuffer = new wchar_t[BUFSIZE]; - DWORD numberOfBytesRead; - - QBENCHMARK { - do { - ReadFile(hndl, nativeBuffer, blockSize, &numberOfBytesRead, NULL); - } while(numberOfBytesRead != 0); - SetFilePointer(hndl, 0, NULL, FILE_BEGIN); - } - delete[] nativeBuffer; - CloseHandle(hndl); -#else - QFAIL("Not running on a non-Windows platform!"); -#endif - } - break; - } -} - -void tst_qfile::seek_data() -{ - QTest::addColumn("testType"); - QTest::newRow("QFile") << QFileBenchmark; -#ifdef QT_BUILD_INTERNAL - QTest::newRow("QFSFileEngine") << QFSFileEngineBenchmark; -#endif - QTest::newRow("Posix FILE*") << PosixBenchmark; -#ifdef Q_OS_WIN - QTest::newRow("Win32 API") << Win32Benchmark; -#endif -} - -void tst_qfile::seek() -{ - QFETCH(tst_qfile::BenchmarkType, testType); - int i = 0; - - switch (testType) { - case QFileBenchmark: { - QFile file(tempDir.filename); - file.open(QIODevice::ReadOnly); - QBENCHMARK { - i=(i+1)%sp_size; - file.seek(seekpos[i]); - } - file.close(); - } - break; -#ifdef QT_BUILD_INTERNAL - case QFSFileEngineBenchmark: { - QFSFileEngine fse(tempDir.filename); - fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered); - QBENCHMARK { - i=(i+1)%sp_size; - fse.seek(seekpos[i]); - } - fse.close(); - } - break; -#endif - case PosixBenchmark: { - QByteArray data = tempDir.filename.toLocal8Bit(); - const char* cfilename = data.constData(); - FILE* cfile = ::fopen(cfilename, "rb"); - QBENCHMARK { - i=(i+1)%sp_size; - ::fseek(cfile, seekpos[i], SEEK_SET); - } - ::fclose(cfile); - } - break; - case QFileFromPosixBenchmark: { - // No gain in benchmarking this case - } - break; - case Win32Benchmark: { -#ifdef Q_OS_WIN - HANDLE hndl; - - // ensure we don't account string conversion - const wchar_t *cfilename = reinterpret_cast(tempDir.filename.utf16()); - - hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); - Q_ASSERT(hndl); - QBENCHMARK { - i=(i+1)%sp_size; - SetFilePointer(hndl, seekpos[i], NULL, 0); - } - CloseHandle(hndl); -#else - QFAIL("Not running on a Windows platform!"); -#endif - } - break; - } -} - -void tst_qfile::open_data() -{ - QTest::addColumn("testType"); - QTest::newRow("QFile") << QFileBenchmark; -#ifdef QT_BUILD_INTERNAL - QTest::newRow("QFSFileEngine") << QFSFileEngineBenchmark; -#endif - QTest::newRow("Posix FILE*") << PosixBenchmark; - QTest::newRow("QFile from FILE*") << QFileFromPosixBenchmark; -#ifdef Q_OS_WIN - QTest::newRow("Win32 API") << Win32Benchmark; -#endif -} - -void tst_qfile::open() -{ - QFETCH(tst_qfile::BenchmarkType, testType); - - switch (testType) { - case QFileBenchmark: { - QBENCHMARK { - QFile file(tempDir.filename); - file.open(QIODevice::ReadOnly); - file.close(); - } - } - break; -#ifdef QT_BUILD_INTERNAL - case QFSFileEngineBenchmark: { - QBENCHMARK { - QFSFileEngine fse(tempDir.filename); - fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered); - fse.close(); - } - } - break; -#endif - case PosixBenchmark: { - // ensure we don't account toLocal8Bit() - QByteArray data = tempDir.filename.toLocal8Bit(); - const char* cfilename = data.constData(); - - QBENCHMARK { - FILE* cfile = ::fopen(cfilename, "rb"); - ::fclose(cfile); - } - } - break; - case QFileFromPosixBenchmark: { - // ensure we don't account toLocal8Bit() - QByteArray data = tempDir.filename.toLocal8Bit(); - const char* cfilename = data.constData(); - FILE* cfile = ::fopen(cfilename, "rb"); - - QBENCHMARK { - QFile file; - file.open(cfile, QIODevice::ReadOnly); - file.close(); - } - ::fclose(cfile); - } - break; - case Win32Benchmark: { -#ifdef Q_OS_WIN - HANDLE hndl; - - // ensure we don't account string conversion - const wchar_t *cfilename = reinterpret_cast(tempDir.filename.utf16()); - - QBENCHMARK { - hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); - Q_ASSERT(hndl); - CloseHandle(hndl); - } -#else - QFAIL("Not running on a non-Windows platform!"); -#endif - } - break; - } -} - -void tst_qfile::readSmallFiles_QFile_data() -{ - readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); - readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); - readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); - readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); - -} - -void tst_qfile::readSmallFiles_QFSFileEngine_data() -{ -#ifdef QT_BUILD_INTERNAL - // Support for buffering dropped at 5.10, so only test Unbuffered - readFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); - readFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); -#else - QSKIP("This test requires -developer-build."); -#endif -} - -void tst_qfile::readSmallFiles_posix_data() -{ - readFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); -} - -void tst_qfile::readSmallFiles_Win32_data() -{ - -#ifdef Q_OS_WIN - readFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); -#else - QSKIP("This is Windows only benchmark."); -#endif -} - -void tst_qfile::readSmallFiles() -{ - QFETCH(tst_qfile::BenchmarkType, testType); - QFETCH(int, blockSize); - QFETCH(QFile::OpenModeFlag, textMode); - QFETCH(QFile::OpenModeFlag, bufferedMode); - - QDir dir(tempDir.path()); - const QStringList files = dir.entryList(QDir::NoDotAndDotDot|QDir::NoSymLinks|QDir::Files); - char buffer[BUFSIZE]; - - switch (testType) { - case QFileBenchmark: { - QList fileList; - for (const QString &file : files) { - QFile *f = new QFile(tempDir.filePath(file)); - f->open(QIODevice::ReadOnly|textMode|bufferedMode); - fileList.append(f); - } - - QBENCHMARK { - for (QFile *const file : qAsConst(fileList)) { - while (!file->atEnd()) - file->read(buffer, blockSize); - } - } - - for (QFile *const file : qAsConst(fileList)) { - file->close(); - delete file; - } - } - break; -#ifdef QT_BUILD_INTERNAL - case QFSFileEngineBenchmark: { - QList fileList; - for (const QString &file : files) { - QFSFileEngine *fse = new QFSFileEngine(tempDir.filePath(file)); - fse->open(QIODevice::ReadOnly|textMode|bufferedMode); - fileList.append(fse); - } - - QBENCHMARK { - for (QFSFileEngine *const fse : qAsConst(fileList)) - while (fse->read(buffer, blockSize)) {} - } - - for (QFSFileEngine *const fse : qAsConst(fileList)) { - fse->close(); - delete fse; - } - } - break; -#endif - case PosixBenchmark: { - QList fileList; - for (const QString &file : files) - fileList.append(::fopen(QFile::encodeName(tempDir.filePath(file)).constData(), "rb")); - - QBENCHMARK { - for (FILE *const cfile : qAsConst(fileList)) { - while (!feof(cfile)) - [[maybe_unused]] auto f = ::fread(buffer, blockSize, 1, cfile); - ::fseek(cfile, 0, SEEK_SET); - } - } - - for (FILE *const cfile : qAsConst(fileList)) - ::fclose(cfile); - } - break; - case QFileFromPosixBenchmark: { - // No gain in benchmarking this case - } - break; - case Win32Benchmark: { -#ifdef Q_OS_WIN - HANDLE hndl; - - // ensure we don't account string conversion - const wchar_t *cfilename = reinterpret_cast(tempDir.filename.utf16()); - - hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); - Q_ASSERT(hndl); - wchar_t* nativeBuffer = new wchar_t[BUFSIZE]; - DWORD numberOfBytesRead; - QBENCHMARK { - do { - ReadFile(hndl, nativeBuffer, blockSize, &numberOfBytesRead, NULL); - } while(numberOfBytesRead != 0); - } - delete nativeBuffer; - CloseHandle(hndl); -#else - QFAIL("Not running on a non-Windows platform!"); -#endif - } - break; - } -} - -QTEST_MAIN(tst_qfile) - -#include "main.moc" diff --git a/tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp b/tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp new file mode 100644 index 0000000000..e7026c70f9 --- /dev/null +++ b/tests/benchmarks/corelib/io/qfile/tst_bench_qfile.cpp @@ -0,0 +1,618 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include + +#include + +#include + +#ifdef Q_OS_WIN +# include +#endif + +#if defined(Q_OS_QNX) && defined(open) +#undef open +#endif + +#define BUFSIZE 1024*512 +#define FACTOR 1024*512 +#define TF_SIZE FACTOR*81 + +// 10 predefined (but random() seek positions +// hardcoded to be comparable over several runs +const int seekpos[] = {int(TF_SIZE*0.52), + int(TF_SIZE*0.23), + int(TF_SIZE*0.73), + int(TF_SIZE*0.77), + int(TF_SIZE*0.80), + int(TF_SIZE*0.12), + int(TF_SIZE*0.53), + int(TF_SIZE*0.21), + int(TF_SIZE*0.27), + int(TF_SIZE*0.78)}; + +const int sp_size = sizeof(seekpos)/sizeof(int); + +class tst_qfile: public QObject +{ +Q_ENUMS(BenchmarkType) +Q_OBJECT +public: + enum BenchmarkType { + QFileBenchmark = 1, +#ifdef QT_BUILD_INTERNAL + QFSFileEngineBenchmark, +#endif + Win32Benchmark, + PosixBenchmark, + QFileFromPosixBenchmark + }; +private slots: + void initTestCase(); + + void open_data(); + void open(); + void seek_data(); + void seek(); + + void readSmallFiles_QFile() { readSmallFiles(); } + void readSmallFiles_QFSFileEngine() { readSmallFiles(); } + void readSmallFiles_posix() { readSmallFiles(); } + void readSmallFiles_Win32() { readSmallFiles(); } + + void readSmallFiles_QFile_data(); + void readSmallFiles_QFSFileEngine_data(); + void readSmallFiles_posix_data(); + void readSmallFiles_Win32_data(); + + void readBigFile_QFile_data(); + void readBigFile_QFSFileEngine_data(); + void readBigFile_posix_data(); + void readBigFile_Win32_data(); + + void readBigFile_QFile() { readBigFile(); } + void readBigFile_QFSFileEngine() { readBigFile(); } + void readBigFile_posix() { readBigFile(); } + void readBigFile_Win32() { readBigFile(); } + +private: + void readFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b); + void readBigFile(); + void readSmallFiles(); + + class TestDataDir : public QTemporaryDir + { + void createFile(); + void createSmallFiles(); + public: + TestDataDir() : QTemporaryDir(), fail(errorString().toLocal8Bit()) + { + if (fail.isEmpty() && !QTemporaryDir::isValid()) + fail = "Failed to create temporary directory for data"; + if (isValid()) + createSmallFiles(); + if (isValid()) + createFile(); + if (isValid()) + QTest::qSleep(2000); // let IO settle + } + bool isValid() { return QTemporaryDir::isValid() && fail.isEmpty(); } + QByteArray fail; + QString filename; + } tempDir; +}; + +Q_DECLARE_METATYPE(tst_qfile::BenchmarkType) +Q_DECLARE_METATYPE(QIODevice::OpenMode) +Q_DECLARE_METATYPE(QIODevice::OpenModeFlag) + +/* None of the tests modify the test data in tempDir, so it's OK to only create + * and tear down the directory once. + */ +void tst_qfile::TestDataDir::createFile() +{ + QFile tmpFile(filePath("testFile")); + if (!tmpFile.open(QIODevice::WriteOnly)) { + fail = "Unable to prepare files for test"; + return; + } +#if 0 // Varied data, rather than filling with '\0' bytes: + for (int row = 0; row < FACTOR; ++row) { + tmpFile.write(QByteArray().fill('0' + row % ('0' - 'z'), 80)); + tmpFile.write("\n"); + } +#else + tmpFile.seek(FACTOR * 80); + tmpFile.putChar('\n'); +#endif + filename = tmpFile.fileName(); + tmpFile.close(); +} + +void tst_qfile::TestDataDir::createSmallFiles() +{ + for (int i = 0; i < 1000; ++i) { + QFile f(filePath(QString::number(i))); + if (!f.open(QIODevice::WriteOnly)) { + fail = "Unable to prepare small files for test"; + return; + } + f.seek(511); + f.putChar('\n'); + f.close(); + } +} + +void tst_qfile::initTestCase() +{ + QVERIFY2(tempDir.isValid(), tempDir.fail.constData()); +} + +void tst_qfile::readFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, + QIODevice::OpenModeFlag b) +{ + QTest::addColumn("testType"); + QTest::addColumn("blockSize"); + QTest::addColumn("textMode"); + QTest::addColumn("bufferedMode"); + + QByteArray flagstring; + if (t & QIODevice::Text) + flagstring += "textMode"; + if (b & QIODevice::Unbuffered) { + if (flagstring.size()) + flagstring += ' '; + flagstring += "unbuffered"; + } + if (flagstring.isEmpty()) + flagstring = "none"; + + const int kbs[] = {1, 2, 8, 16, 32, 512}; + for (int kb : kbs) { + const int size = 1024 * kb; + QTest::addRow("BS: %d, Flags: %s", size, flagstring.constData()) + << type << size << t << b; + } +} + +void tst_qfile::readBigFile_QFile_data() +{ + readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); + readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); + readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); + +} + +void tst_qfile::readBigFile_QFSFileEngine_data() +{ +#ifdef QT_BUILD_INTERNAL + // Support for buffering dropped at 5.10, so only test Unbuffered + readFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); +#else + QSKIP("This test requires -developer-build."); +#endif +} + +void tst_qfile::readBigFile_posix_data() +{ + readFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); +} + +void tst_qfile::readBigFile_Win32_data() +{ +#ifdef Q_OS_WIN + readFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); +#else + QSKIP("This is Windows only benchmark."); +#endif +} + +void tst_qfile::readBigFile() +{ + QFETCH(tst_qfile::BenchmarkType, testType); + QFETCH(int, blockSize); + QFETCH(QFile::OpenModeFlag, textMode); + QFETCH(QFile::OpenModeFlag, bufferedMode); + + char buffer[BUFSIZE]; + switch (testType) { + case QFileBenchmark: { + QFile file(tempDir.filename); + file.open(QIODevice::ReadOnly|textMode|bufferedMode); + QBENCHMARK { + while(!file.atEnd()) + file.read(blockSize); + file.reset(); + } + file.close(); + } + break; +#ifdef QT_BUILD_INTERNAL + case QFSFileEngineBenchmark: { + QFSFileEngine fse(tempDir.filename); + fse.open(QIODevice::ReadOnly|textMode|bufferedMode); + QBENCHMARK { + //qWarning() << fse.supportsExtension(QAbstractFileEngine::AtEndExtension); + while (fse.read(buffer, blockSize)) {} + fse.seek(0); + } + fse.close(); + } + break; +#endif + case PosixBenchmark: { + QByteArray data = tempDir.filename.toLocal8Bit(); + const char* cfilename = data.constData(); + FILE* cfile = ::fopen(cfilename, "rb"); + QBENCHMARK { + while(!feof(cfile)) + [[maybe_unused]] auto r = ::fread(buffer, blockSize, 1, cfile); + ::fseek(cfile, 0, SEEK_SET); + } + ::fclose(cfile); + } + break; + case QFileFromPosixBenchmark: { + // No gain in benchmarking this case + } + break; + case Win32Benchmark: { +#ifdef Q_OS_WIN + HANDLE hndl; + + // ensure we don't account string conversion + const wchar_t *cfilename = reinterpret_cast(tempDir.filename.utf16()); + + hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + Q_ASSERT(hndl); + wchar_t* nativeBuffer = new wchar_t[BUFSIZE]; + DWORD numberOfBytesRead; + + QBENCHMARK { + do { + ReadFile(hndl, nativeBuffer, blockSize, &numberOfBytesRead, NULL); + } while(numberOfBytesRead != 0); + SetFilePointer(hndl, 0, NULL, FILE_BEGIN); + } + delete[] nativeBuffer; + CloseHandle(hndl); +#else + QFAIL("Not running on a non-Windows platform!"); +#endif + } + break; + } +} + +void tst_qfile::seek_data() +{ + QTest::addColumn("testType"); + QTest::newRow("QFile") << QFileBenchmark; +#ifdef QT_BUILD_INTERNAL + QTest::newRow("QFSFileEngine") << QFSFileEngineBenchmark; +#endif + QTest::newRow("Posix FILE*") << PosixBenchmark; +#ifdef Q_OS_WIN + QTest::newRow("Win32 API") << Win32Benchmark; +#endif +} + +void tst_qfile::seek() +{ + QFETCH(tst_qfile::BenchmarkType, testType); + int i = 0; + + switch (testType) { + case QFileBenchmark: { + QFile file(tempDir.filename); + file.open(QIODevice::ReadOnly); + QBENCHMARK { + i=(i+1)%sp_size; + file.seek(seekpos[i]); + } + file.close(); + } + break; +#ifdef QT_BUILD_INTERNAL + case QFSFileEngineBenchmark: { + QFSFileEngine fse(tempDir.filename); + fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered); + QBENCHMARK { + i=(i+1)%sp_size; + fse.seek(seekpos[i]); + } + fse.close(); + } + break; +#endif + case PosixBenchmark: { + QByteArray data = tempDir.filename.toLocal8Bit(); + const char* cfilename = data.constData(); + FILE* cfile = ::fopen(cfilename, "rb"); + QBENCHMARK { + i=(i+1)%sp_size; + ::fseek(cfile, seekpos[i], SEEK_SET); + } + ::fclose(cfile); + } + break; + case QFileFromPosixBenchmark: { + // No gain in benchmarking this case + } + break; + case Win32Benchmark: { +#ifdef Q_OS_WIN + HANDLE hndl; + + // ensure we don't account string conversion + const wchar_t *cfilename = reinterpret_cast(tempDir.filename.utf16()); + + hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + Q_ASSERT(hndl); + QBENCHMARK { + i=(i+1)%sp_size; + SetFilePointer(hndl, seekpos[i], NULL, 0); + } + CloseHandle(hndl); +#else + QFAIL("Not running on a Windows platform!"); +#endif + } + break; + } +} + +void tst_qfile::open_data() +{ + QTest::addColumn("testType"); + QTest::newRow("QFile") << QFileBenchmark; +#ifdef QT_BUILD_INTERNAL + QTest::newRow("QFSFileEngine") << QFSFileEngineBenchmark; +#endif + QTest::newRow("Posix FILE*") << PosixBenchmark; + QTest::newRow("QFile from FILE*") << QFileFromPosixBenchmark; +#ifdef Q_OS_WIN + QTest::newRow("Win32 API") << Win32Benchmark; +#endif +} + +void tst_qfile::open() +{ + QFETCH(tst_qfile::BenchmarkType, testType); + + switch (testType) { + case QFileBenchmark: { + QBENCHMARK { + QFile file(tempDir.filename); + file.open(QIODevice::ReadOnly); + file.close(); + } + } + break; +#ifdef QT_BUILD_INTERNAL + case QFSFileEngineBenchmark: { + QBENCHMARK { + QFSFileEngine fse(tempDir.filename); + fse.open(QIODevice::ReadOnly | QIODevice::Unbuffered); + fse.close(); + } + } + break; +#endif + case PosixBenchmark: { + // ensure we don't account toLocal8Bit() + QByteArray data = tempDir.filename.toLocal8Bit(); + const char* cfilename = data.constData(); + + QBENCHMARK { + FILE* cfile = ::fopen(cfilename, "rb"); + ::fclose(cfile); + } + } + break; + case QFileFromPosixBenchmark: { + // ensure we don't account toLocal8Bit() + QByteArray data = tempDir.filename.toLocal8Bit(); + const char* cfilename = data.constData(); + FILE* cfile = ::fopen(cfilename, "rb"); + + QBENCHMARK { + QFile file; + file.open(cfile, QIODevice::ReadOnly); + file.close(); + } + ::fclose(cfile); + } + break; + case Win32Benchmark: { +#ifdef Q_OS_WIN + HANDLE hndl; + + // ensure we don't account string conversion + const wchar_t *cfilename = reinterpret_cast(tempDir.filename.utf16()); + + QBENCHMARK { + hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + Q_ASSERT(hndl); + CloseHandle(hndl); + } +#else + QFAIL("Not running on a non-Windows platform!"); +#endif + } + break; + } +} + +void tst_qfile::readSmallFiles_QFile_data() +{ + readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); + readFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); + readFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); + +} + +void tst_qfile::readSmallFiles_QFSFileEngine_data() +{ +#ifdef QT_BUILD_INTERNAL + // Support for buffering dropped at 5.10, so only test Unbuffered + readFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); +#else + QSKIP("This test requires -developer-build."); +#endif +} + +void tst_qfile::readSmallFiles_posix_data() +{ + readFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); +} + +void tst_qfile::readSmallFiles_Win32_data() +{ + +#ifdef Q_OS_WIN + readFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); +#else + QSKIP("This is Windows only benchmark."); +#endif +} + +void tst_qfile::readSmallFiles() +{ + QFETCH(tst_qfile::BenchmarkType, testType); + QFETCH(int, blockSize); + QFETCH(QFile::OpenModeFlag, textMode); + QFETCH(QFile::OpenModeFlag, bufferedMode); + + QDir dir(tempDir.path()); + const QStringList files = dir.entryList(QDir::NoDotAndDotDot|QDir::NoSymLinks|QDir::Files); + char buffer[BUFSIZE]; + + switch (testType) { + case QFileBenchmark: { + QList fileList; + for (const QString &file : files) { + QFile *f = new QFile(tempDir.filePath(file)); + f->open(QIODevice::ReadOnly|textMode|bufferedMode); + fileList.append(f); + } + + QBENCHMARK { + for (QFile *const file : qAsConst(fileList)) { + while (!file->atEnd()) + file->read(buffer, blockSize); + } + } + + for (QFile *const file : qAsConst(fileList)) { + file->close(); + delete file; + } + } + break; +#ifdef QT_BUILD_INTERNAL + case QFSFileEngineBenchmark: { + QList fileList; + for (const QString &file : files) { + QFSFileEngine *fse = new QFSFileEngine(tempDir.filePath(file)); + fse->open(QIODevice::ReadOnly|textMode|bufferedMode); + fileList.append(fse); + } + + QBENCHMARK { + for (QFSFileEngine *const fse : qAsConst(fileList)) + while (fse->read(buffer, blockSize)) {} + } + + for (QFSFileEngine *const fse : qAsConst(fileList)) { + fse->close(); + delete fse; + } + } + break; +#endif + case PosixBenchmark: { + QList fileList; + for (const QString &file : files) + fileList.append(::fopen(QFile::encodeName(tempDir.filePath(file)).constData(), "rb")); + + QBENCHMARK { + for (FILE *const cfile : qAsConst(fileList)) { + while (!feof(cfile)) + [[maybe_unused]] auto f = ::fread(buffer, blockSize, 1, cfile); + ::fseek(cfile, 0, SEEK_SET); + } + } + + for (FILE *const cfile : qAsConst(fileList)) + ::fclose(cfile); + } + break; + case QFileFromPosixBenchmark: { + // No gain in benchmarking this case + } + break; + case Win32Benchmark: { +#ifdef Q_OS_WIN + HANDLE hndl; + + // ensure we don't account string conversion + const wchar_t *cfilename = reinterpret_cast(tempDir.filename.utf16()); + + hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + Q_ASSERT(hndl); + wchar_t* nativeBuffer = new wchar_t[BUFSIZE]; + DWORD numberOfBytesRead; + QBENCHMARK { + do { + ReadFile(hndl, nativeBuffer, blockSize, &numberOfBytesRead, NULL); + } while(numberOfBytesRead != 0); + } + delete nativeBuffer; + CloseHandle(hndl); +#else + QFAIL("Not running on a non-Windows platform!"); +#endif + } + break; + } +} + +QTEST_MAIN(tst_qfile) + +#include "tst_bench_qfile.moc" -- cgit v1.2.3