/**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #ifdef Q_OS_WIN # include # include #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, QFSFileEngineBenchmark, Win32Benchmark, PosixBenchmark, QFileFromPosixBenchmark }; private slots: void initTestCase(); void cleanupTestCase(); void open_data(); void open(); void seek_data(); void seek(); void readSmallFiles_QFile(); void readSmallFiles_QFSFileEngine(); void readSmallFiles_posix(); void readSmallFiles_Win32(); 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(); void readBigFile_QFSFileEngine(); void readBigFile_posix(); void readBigFile_Win32(); private: void readBigFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b); void readBigFile(); void readSmallFiles_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b); void readSmallFiles(); void createFile(); void fillFile(int factor=FACTOR); void removeFile(); void createSmallFiles(); void removeSmallFiles(); QString filename; QString tmpDirName; }; Q_DECLARE_METATYPE(tst_qfile::BenchmarkType) Q_DECLARE_METATYPE(QIODevice::OpenMode) Q_DECLARE_METATYPE(QIODevice::OpenModeFlag) void tst_qfile::createFile() { removeFile(); // Cleanup in case previous test case aborted before cleaning up QTemporaryFile tmpFile; tmpFile.setAutoRemove(false); if (!tmpFile.open()) ::exit(1); filename = tmpFile.fileName(); tmpFile.close(); } void tst_qfile::removeFile() { if (!filename.isEmpty()) QFile::remove(filename); } void tst_qfile::fillFile(int factor) { QFile tmpFile(filename); tmpFile.open(QIODevice::WriteOnly); //for (int row=0; row("testType"); QTest::addColumn("blockSize"); QTest::addColumn("textMode"); QTest::addColumn("bufferedMode"); const int bs[] = {1024, 1024*2, 1024*8, 1024*16, 1024*32,1024*512}; int bs_entries = sizeof(bs)/sizeof(const int); QString flagstring; if (t & QIODevice::Text) flagstring += "textMode "; if (b & QIODevice::Unbuffered) flagstring += "unbuffered "; if (flagstring.isEmpty()) flagstring = "none"; for (int i=0; i("testType"); QTest::newRow("QFile") << QFileBenchmark; QTest::newRow("QFSFileEngine") << QFSFileEngineBenchmark; 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; createFile(); fillFile(); switch (testType) { case(QFileBenchmark): { QFile file(filename); file.open(QIODevice::ReadOnly); QBENCHMARK { i=(i+1)%sp_size; file.seek(seekpos[i]); } file.close(); } break; case(QFSFileEngineBenchmark): { QFSFileEngine fse(filename); fse.open(QIODevice::ReadOnly); QBENCHMARK { i=(i+1)%sp_size; fse.seek(seekpos[i]); } fse.close(); } break; case(PosixBenchmark): { QByteArray data = 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 wchar_t* cfilename = (wchar_t*)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 plattform!"); #endif } break; } removeFile(); } void tst_qfile::open_data() { QTest::addColumn("testType"); QTest::newRow("QFile") << QFileBenchmark; QTest::newRow("QFSFileEngine") << QFSFileEngineBenchmark; 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); createFile(); switch (testType) { case(QFileBenchmark): { QBENCHMARK { QFile file( filename ); file.open( QIODevice::ReadOnly ); file.close(); } } break; case(QFSFileEngineBenchmark): { QBENCHMARK { QFSFileEngine fse(filename); fse.open(QIODevice::ReadOnly); fse.close(); } } break; case(PosixBenchmark): { // ensure we don't account toLocal8Bit() QByteArray data = 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 = 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 wchar_t* cfilename = (wchar_t*)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; } removeFile(); } void tst_qfile::readSmallFiles_QFile() { readSmallFiles(); } void tst_qfile::readSmallFiles_QFSFileEngine() { readSmallFiles(); } void tst_qfile::readSmallFiles_posix() { readSmallFiles(); } void tst_qfile::readSmallFiles_Win32() { readSmallFiles(); } void tst_qfile::readSmallFiles_QFile_data() { readSmallFiles_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); readSmallFiles_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); readSmallFiles_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); readSmallFiles_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); } void tst_qfile::readSmallFiles_QFSFileEngine_data() { readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::NotOpen); readSmallFiles_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); } void tst_qfile::readSmallFiles_posix_data() { readSmallFiles_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); } void tst_qfile::readSmallFiles_Win32_data() { readSmallFiles_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); } void tst_qfile::readSmallFiles_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b) { QTest::addColumn("testType"); QTest::addColumn("blockSize"); QTest::addColumn("textMode"); QTest::addColumn("bufferedMode"); const int bs[] = {1024, 1024*2, 1024*8, 1024*16, 1024*32,1024*512}; int bs_entries = sizeof(bs)/sizeof(const int); QString flagstring; if (t & QIODevice::Text) flagstring += "textMode "; if (b & QIODevice::Unbuffered) flagstring += "unbuffered "; if (flagstring.isEmpty()) flagstring = "none"; for (int i=0; i fileList; Q_FOREACH(QString file, files) { QFile *f = new QFile(tmpDirName+ "/" + file); f->open(QIODevice::ReadOnly|textMode|bufferedMode); fileList.append(f); } QBENCHMARK { Q_FOREACH(QFile *file, fileList) { while (!file->atEnd()) { file->read(buffer, blockSize); } } } Q_FOREACH(QFile *file, fileList) { file->close(); delete file; } } break; case(QFSFileEngineBenchmark): { QList fileList; Q_FOREACH(QString file, files) { QFSFileEngine *fse = new QFSFileEngine(tmpDirName+ "/" + file); fse->open(QIODevice::ReadOnly|textMode|bufferedMode); fileList.append(fse); } QBENCHMARK { Q_FOREACH(QFSFileEngine *fse, fileList) { while (fse->read(buffer, blockSize)); } } Q_FOREACH(QFSFileEngine *fse, fileList) { fse->close(); delete fse; } } break; case(PosixBenchmark): { QList fileList; Q_FOREACH(QString file, files) { fileList.append(::fopen(QFile::encodeName(tmpDirName+ "/" + file).constData(), "rb")); } QBENCHMARK { Q_FOREACH(FILE* cfile, fileList) { while(!feof(cfile)) ::fread(buffer, blockSize, 1, cfile); ::fseek(cfile, 0, SEEK_SET); } } Q_FOREACH(FILE* cfile, 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 wchar_t* cfilename = (wchar_t*)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; } removeSmallFiles(); delete[] buffer; } QTEST_MAIN(tst_qfile) #include "main.moc"