diff options
Diffstat (limited to 'tests/benchmarks/corelib/io')
-rw-r--r-- | tests/benchmarks/corelib/io/io.pro | 9 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qdir/qdir.pro | 8 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qdir/tst_qdir.cpp | 198 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qdiriterator/main.cpp | 251 | ||||
-rwxr-xr-x | tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro | 23 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp | 678 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h | 99 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qfile/main.cpp | 675 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qfile/qfile.pro | 7 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qfileinfo/main.cpp | 83 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro | 12 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qiodevice/main.cpp | 107 | ||||
-rwxr-xr-x | tests/benchmarks/corelib/io/qiodevice/qiodevice.pro | 13 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qtemporaryfile/main.cpp | 103 | ||||
-rw-r--r-- | tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro | 12 |
15 files changed, 2278 insertions, 0 deletions
diff --git a/tests/benchmarks/corelib/io/io.pro b/tests/benchmarks/corelib/io/io.pro new file mode 100644 index 0000000..97445d7 --- /dev/null +++ b/tests/benchmarks/corelib/io/io.pro @@ -0,0 +1,9 @@ +TEMPLATE = subdirs +SUBDIRS = \ + qdir \ + qdiriterator \ + qfile \ + qfileinfo \ + qiodevice \ + qtemporaryfile + diff --git a/tests/benchmarks/corelib/io/qdir/qdir.pro b/tests/benchmarks/corelib/io/qdir/qdir.pro new file mode 100644 index 0000000..2cdebfd --- /dev/null +++ b/tests/benchmarks/corelib/io/qdir/qdir.pro @@ -0,0 +1,8 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qdir +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += tst_qdir.cpp diff --git a/tests/benchmarks/corelib/io/qdir/tst_qdir.cpp b/tests/benchmarks/corelib/io/qdir/tst_qdir.cpp new file mode 100644 index 0000000..aea9fd0 --- /dev/null +++ b/tests/benchmarks/corelib/io/qdir/tst_qdir.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#ifdef Q_OS_WIN +# include <windows.h> +#else +# include <sys/stat.h> +# include <sys/types.h> +# include <dirent.h> +# include <unistd.h> +#endif + +class Test : public QObject{ + Q_OBJECT +public slots: + void initTestCase() { + QDir testdir = QDir::tempPath(); + + const QString subfolder_name = QLatin1String("test_speed"); + QVERIFY(testdir.mkdir(subfolder_name)); + QVERIFY(testdir.cd(subfolder_name)); + + for (uint i=0; i<10000; ++i) { + QFile file(testdir.absolutePath() + "/testfile_" + QString::number(i)); + file.open(QIODevice::WriteOnly); + } + } + void cleanupTestCase() { + { + QDir testdir(QDir::tempPath() + QLatin1String("/test_speed")); + testdir.setSorting(QDir::Unsorted); + testdir.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden); + foreach (const QString &filename, testdir.entryList()) { + testdir.remove(filename); + } + } + const QDir temp = QDir(QDir::tempPath()); + temp.rmdir(QLatin1String("test_speed")); + } +private slots: + void baseline() {} + + void sizeSpeed() { + QDir testdir(QDir::tempPath() + QLatin1String("/test_speed")); + QBENCHMARK { + QFileInfoList fileInfoList = testdir.entryInfoList(QDir::Files, QDir::Unsorted); + foreach (const QFileInfo &fileInfo, fileInfoList) { + fileInfo.isDir(); + fileInfo.size(); + } + } + } + void sizeSpeedIterator() { + QDir testdir(QDir::tempPath() + QLatin1String("/test_speed")); + QBENCHMARK { + QDirIterator dit(testdir.path(), QDir::Files); + while (dit.hasNext()) { + dit.fileInfo().isDir(); + dit.fileInfo().size(); + dit.next(); + } + } + } + + void sizeSpeedWithoutFilter() { + QDir testdir(QDir::tempPath() + QLatin1String("/test_speed")); + QBENCHMARK { + QFileInfoList fileInfoList = testdir.entryInfoList(QDir::NoFilter, QDir::Unsorted); + foreach (const QFileInfo &fileInfo, fileInfoList) { + fileInfo.size(); + } + } + } + void sizeSpeedWithoutFilterIterator() { + QDir testdir(QDir::tempPath() + QLatin1String("/test_speed")); + QBENCHMARK { + QDirIterator dit(testdir.path()); + while (dit.hasNext()) { + dit.fileInfo().isDir(); + dit.fileInfo().size(); + dit.next(); + } + } + } + + void sizeSpeedWithoutFileInfoList() { + QDir testdir(QDir::tempPath() + QLatin1String("/test_speed")); + testdir.setSorting(QDir::Unsorted); + QBENCHMARK { + QStringList fileList = testdir.entryList(QDir::NoFilter, QDir::Unsorted); + foreach (const QString &filename, fileList) { + QFileInfo fileInfo(filename); + fileInfo.size(); + } + } + } + + void iDontWantAnyStat() { + QDir testdir(QDir::tempPath() + QLatin1String("/test_speed")); + testdir.setSorting(QDir::Unsorted); + testdir.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden); + QBENCHMARK { + QStringList fileList = testdir.entryList(QDir::NoFilter, QDir::Unsorted); + foreach (const QString &filename, fileList) { + + } + } + } + void iDontWantAnyStatIterator() { + QBENCHMARK { + QDirIterator dit(QDir::tempPath() + QLatin1String("/test_speed")); + while (dit.hasNext()) { + dit.next(); + } + } + } + + void sizeSpeedWithoutFilterLowLevel() { +#ifdef Q_OS_WIN + const wchar_t *dirpath = (wchar_t*)testdir.absolutePath().utf16(); + wchar_t appendedPath[MAX_PATH]; + wcscpy(appendedPath, dirpath); + wcscat(appendedPath, L"\\*"); + + WIN32_FIND_DATA fd; + HANDLE hSearch = FindFirstFileW(appendedPath, &fd); + QVERIFY(hSearch == INVALID_HANDLE_VALUE); + + QBENCHMARK { + do { + + } while (FindNextFile(hSearch, &fd)); + } + FindClose(hSearch); +#else + QDir testdir(QDir::tempPath() + QLatin1String("/test_speed")); + DIR *dir = opendir(qPrintable(testdir.absolutePath())); + QVERIFY(dir); + + QVERIFY(!chdir(qPrintable(testdir.absolutePath()))); + QBENCHMARK { + struct dirent *item = readdir(dir); + while (item) { + char *fileName = item->d_name; + + struct stat fileStat; + QVERIFY(!stat(fileName, &fileStat)); + + item = readdir(dir); + } + } + closedir(dir); +#endif + } +}; + +QTEST_MAIN(Test) +#include "tst_qdir.moc" diff --git a/tests/benchmarks/corelib/io/qdiriterator/main.cpp b/tests/benchmarks/corelib/io/qdiriterator/main.cpp new file mode 100644 index 0000000..afa6b7b --- /dev/null +++ b/tests/benchmarks/corelib/io/qdiriterator/main.cpp @@ -0,0 +1,251 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QDebug> +#include <QDirIterator> +#include <QString> + +#ifdef Q_OS_WIN +# include <windows.h> +# include <atlbase.h> +#else +# include <sys/stat.h> +# include <sys/types.h> +# include <dirent.h> +# include <errno.h> +# include <string.h> +#endif + +#include <qtest.h> + +#include "qfilesystemiterator.h" + +class tst_qdiriterator : public QObject +{ + Q_OBJECT +private slots: + void posix(); + void posix_data() { data(); } + void diriterator(); + void diriterator_data() { data(); } + void fsiterator(); + void fsiterator_data() { data(); } + void data(); +}; + + +void tst_qdiriterator::data() +{ +#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) + QByteArray qtdir = qPrintable(QCoreApplication::applicationDirPath()); + qtdir += "/depot"; +#else +#if defined(Q_OS_WIN) + const char *qtdir = "C:\\depot\\qt\\main"; +#else + const char *qtdir = ::getenv("QTDIR"); +#endif + if (!qtdir) { + fprintf(stderr, "QTDIR not set\n"); + exit(1); + } +#endif + + QTest::addColumn<QByteArray>("dirpath"); + QByteArray ba = QByteArray(qtdir) + "/src/corelib"; + QByteArray ba1 = ba + "/io"; + QTest::newRow(ba) << ba; + //QTest::newRow(ba1) << ba1; +} + +#ifdef Q_OS_WIN +static int posix_helper(const wchar_t *dirpath) +{ + int count = 0; + HANDLE hSearch; + WIN32_FIND_DATA fd; + + const size_t origDirPathLength = wcslen(dirpath); + + wchar_t appendedPath[MAX_PATH]; + wcscpy(appendedPath, dirpath); + wcscat(appendedPath, L"\\*"); + hSearch = FindFirstFile(appendedPath, &fd); + appendedPath[origDirPathLength] = 0; + + if (hSearch == INVALID_HANDLE_VALUE) { + qWarning("FindFirstFile failed"); + return count; + } + + do { + if (!(fd.cFileName[0] == L'.' && fd.cFileName[1] == 0) && + !(fd.cFileName[0] == L'.' && fd.cFileName[1] == L'.' && fd.cFileName[2] == 0)) + { + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + wcscat(appendedPath, L"\\"); + wcscat(appendedPath, fd.cFileName); + count += posix_helper(appendedPath); + appendedPath[origDirPathLength] = 0; + } + else { + ++count; + } + } + } while (FindNextFile(hSearch, &fd)); + FindClose(hSearch); + + return count; +} + +#else + +static int posix_helper(const char *dirpath) +{ + //qDebug() << "DIR" << dirpath; + DIR *dir = ::opendir(dirpath); + if (!dir) + return 0; + + dirent *entry = 0; + + int count = 0; + while ((entry = ::readdir(dir))) { + if (qstrcmp(entry->d_name, ".") == 0) + continue; + if (qstrcmp(entry->d_name, "..") == 0) + continue; + ++count; + QByteArray ba = dirpath; + ba += '/'; + ba += entry->d_name; + struct stat st; + lstat(ba.constData(), &st); + if (S_ISDIR(st.st_mode)) + count += posix_helper(ba.constData()); + } + + ::closedir(dir); + return count; +} +#endif + + +void tst_qdiriterator::posix() +{ + QFETCH(QByteArray, dirpath); + + int count = 0; + QString path(dirpath); + QBENCHMARK { +#ifdef Q_OS_WIN + count = posix_helper(path.utf16()); +#else + count = posix_helper(dirpath.constData()); +#endif + } + qDebug() << count; +} + +void tst_qdiriterator::diriterator() +{ + QFETCH(QByteArray, dirpath); + + int count = 0; + + QBENCHMARK { + int c = 0; + + QDirIterator dir(dirpath, + //QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, + //QDir::AllEntries | QDir::Hidden, + QDir::Files, + QDirIterator::Subdirectories); + + while (dir.hasNext()) { + dir.next(); + //printf("%s\n", qPrintable(dir.fileName())); + 0 && printf("%d %s\n", + dir.fileInfo().isDir(), + //qPrintable(dir.fileInfo().absoluteFilePath()), + //qPrintable(dir.path()), + qPrintable(dir.filePath())); + ++c; + } + count = c; + } + qDebug() << count; +} + +void tst_qdiriterator::fsiterator() +{ + QFETCH(QByteArray, dirpath); + + int count = 0; + int dump = 0; + + QBENCHMARK { + int c = 0; + + dump && printf("\n\n\n\n"); + QFileSystemIterator dir(dirpath, + //QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, + //QDir::AllEntries | QDir::Hidden, + //QDir::Files | QDir::NoDotAndDotDot, + QDir::Files, + QFileSystemIterator::Subdirectories); + + for (; !dir.atEnd(); dir.next()) { + dump && printf("%d %s\n", + dir.fileInfo().isDir(), + //qPrintable(dir.fileInfo().absoluteFilePath()), + //qPrintable(dir.path()), + qPrintable(dir.filePath()) + ); + ++c; + } + count = c; + } + qDebug() << count; +} + +QTEST_MAIN(tst_qdiriterator) + +#include "main.moc" diff --git a/tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro b/tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro new file mode 100755 index 0000000..e06d746 --- /dev/null +++ b/tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro @@ -0,0 +1,23 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qdiriterator +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui + +CONFIG += release +CONFIG += debug + + +SOURCES += main.cpp + +SOURCES += qfilesystemiterator.cpp +HEADERS += qfilesystemiterator.h + +wince*|symbian: { + corelibdir.sources = $$QT_SOURCE_TREE/src/corelib + corelibdir.path = ./depot/src + DEPLOYMENT += corelibdir +} + diff --git a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp new file mode 100644 index 0000000..267d53f --- /dev/null +++ b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.cpp @@ -0,0 +1,678 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \since 4.5 + \class QFileSystemIterator + \brief The QFileSystemIterator class provides an iterator for directory entrylists. + + You can use QFileSystemIterator to navigate entries of a directory one at a time. + It is similar to QDir::entryList() and QDir::entryInfoList(), but because + it lists entries one at a time instead of all at once, it scales better + and is more suitable for large directories. It also supports listing + directory contents recursively, and following symbolic links. Unlike + QDir::entryList(), QFileSystemIterator does not support sorting. + + The QFileSystemIterator constructor takes a QDir or a directory as + argument. After construction, the iterator is located before the first + directory entry. Here's how to iterate over all the entries sequentially: + + \snippet doc/src/snippets/code/src.corelib.io.qdiriterator.cpp 0 + + The next() function returns the path to the next directory entry and + advances the iterator. You can also call filePath() to get the current + file path without advancing the iterator. The fileName() function returns + only the name of the file, similar to how QDir::entryList() works. You can + also call fileInfo() to get a QFileInfo for the current entry. + + Unlike Qt's container iterators, QFileSystemIterator is uni-directional (i.e., + you cannot iterate directories in reverse order) and does not allow random + access. + + QFileSystemIterator works with all supported file engines, and is implemented + using QAbstractFileEngineIterator. + + \sa QDir, QDir::entryList(), QAbstractFileEngineIterator +*/ + +/*! \enum QFileSystemIterator::IteratorFlag + + This enum describes flags that you can combine to configure the behavior + of QFileSystemIterator. + + \value NoIteratorFlags The default value, representing no flags. The + iterator will return entries for the assigned path. + + \value Subdirectories List entries inside all subdirectories as well. + + \value FollowSymlinks When combined with Subdirectories, this flag + enables iterating through all subdirectories of the assigned path, + following all symbolic links. Symbolic link loops (e.g., "link" => "." or + "link" => "..") are automatically detected and ignored. +*/ + +#include "qfilesystemiterator.h" + +#include <QDebug> +#include <QtCore/qset.h> +#include <QtCore/qstack.h> +#include <QtCore/qvariant.h> + +#ifdef Q_OS_WIN +# include <windows.h> +# include <atlbase.h> +#else +# include <sys/stat.h> +# include <sys/types.h> +# include <dirent.h> +# include <errno.h> +#endif + +QT_BEGIN_NAMESPACE + +class QFileSystemIteratorPrivate +{ +public: + QFileSystemIteratorPrivate(const QString &path, const QStringList &nameFilters, + QDir::Filters filters, QFileSystemIterator::IteratorFlags flags); + ~QFileSystemIteratorPrivate(); + + void pushSubDirectory(const QByteArray &path); + void advance(); + bool isAcceptable() const; + bool shouldFollowDirectory(const QFileInfo &); + //bool matchesFilters(const QAbstractFileEngineIterator *it) const; + inline bool atEnd() const { return m_dirPaths.isEmpty(); } + +#ifdef Q_OS_WIN + QStack<HANDLE> m_dirStructs; + WIN32_FIND_DATA* m_entry; + WIN32_FIND_DATA m_fileSearchResult; + bool m_bFirstSearchResult; +#else + QStack<DIR *> m_dirStructs; + dirent *m_entry; +#endif + + QSet<QString> visitedLinks; + QStack<QByteArray> m_dirPaths; + QFileInfo fileInfo; + QString currentFilePath; + QFileSystemIterator::IteratorFlags iteratorFlags; + QDir::Filters filters; + QStringList nameFilters; + + enum { DontShowDir, ShowDotDotDir, ShowDotDir, ShowDir } + m_currentDirShown, m_nextDirShown; + + QFileSystemIterator *q; + +private: + bool advanceHelper(); // returns true if we know we have something suitable +}; + +/*! + \internal +*/ +QFileSystemIteratorPrivate::QFileSystemIteratorPrivate(const QString &path, + const QStringList &nameFilters, QDir::Filters filters, + QFileSystemIterator::IteratorFlags flags) + : iteratorFlags(flags) +{ + if (filters == QDir::NoFilter) + filters = QDir::AllEntries; + this->filters = filters; + this->nameFilters = nameFilters; + + fileInfo.setFile(path); + QString dir = fileInfo.isSymLink() ? fileInfo.canonicalFilePath() : path; + pushSubDirectory(dir.toLocal8Bit()); + // skip to acceptable entry + while (true) { + if (atEnd()) + return; + if (isAcceptable()) + return; + if (advanceHelper()) + return; + } +} + +/*! + \internal +*/ +QFileSystemIteratorPrivate::~QFileSystemIteratorPrivate() +{ +#ifdef Q_OS_WIN + while (!m_dirStructs.isEmpty()) + ::FindClose(m_dirStructs.pop()); +#else + while (!m_dirStructs.isEmpty()) + ::closedir(m_dirStructs.pop()); +#endif +} + +#ifdef Q_OS_WIN +static bool isDotOrDotDot(const wchar_t* name) +{ + if (name[0] == L'.' && name[1] == 0) + return true; + if (name[0] == L'.' && name[1] == L'.' && name[2] == 0) + return true; + return false; +} +#else +static bool isDotOrDotDot(const char *name) +{ + if (name[0] == '.' && name[1] == 0) + return true; + if (name[0] == '.' && name[1] == '.' && name[2] == 0) + return true; + return false; +} +#endif + +/*! + \internal +*/ +void QFileSystemIteratorPrivate::pushSubDirectory(const QByteArray &path) +{ +/* + if (iteratorFlags & QFileSystemIterator::FollowSymlinks) { + if (fileInfo.filePath() != path) + fileInfo.setFile(path); + if (fileInfo.isSymLink()) { + visitedLinks << fileInfo.canonicalFilePath(); + } else { + visitedLinks << fileInfo.absoluteFilePath(); + } + } +*/ + +#ifdef Q_OS_WIN + wchar_t szSearchPath[MAX_PATH]; + wcscpy(szSearchPath, QString(path).utf16()); + wcscat(szSearchPath, L"\\*"); + HANDLE dir = FindFirstFile(szSearchPath, &m_fileSearchResult); + m_bFirstSearchResult = true; +#else + DIR *dir = ::opendir(path.constData()); + //m_entry = ::readdir(dir); + //while (m_entry && isDotOrDotDot(m_entry->d_name)) + // m_entry = ::readdir(m_dirStructs.top()); +#endif + m_dirStructs.append(dir); + m_dirPaths.append(path); + m_entry = 0; + if (filters & QDir::Dirs) + m_nextDirShown = ShowDir; + else + m_nextDirShown = DontShowDir; + m_currentDirShown = DontShowDir; +} + +/*! + \internal +*/ +bool QFileSystemIteratorPrivate::isAcceptable() const +{ + if (!m_entry) + return false; + return true; +} + +/*! + \internal +*/ + + +void QFileSystemIteratorPrivate::advance() +{ + while (true) { + if (advanceHelper()) + return; + if (atEnd()) + return; + if (isAcceptable()) + return; + } +} + +bool QFileSystemIteratorPrivate::advanceHelper() +{ + if (m_dirStructs.isEmpty()) + return true; + + //printf("ADV %d %d\n", int(m_currentDirShown), int(m_nextDirShown)); + + if ((filters & QDir::Dirs)) { + m_currentDirShown = m_nextDirShown; + if (m_nextDirShown == ShowDir) { + //printf("RESTING ON DIR %s %x\n", m_dirPaths.top().constData(), int(filters)); + m_nextDirShown = (filters & QDir::NoDotAndDotDot) ? DontShowDir : ShowDotDir; + // skip start directory itself + if (m_dirStructs.size() == 1 && m_currentDirShown == ShowDir) + return advanceHelper(); + return true; + } + if (m_nextDirShown == ShowDotDir) { + //printf("RESTING ON DOT %s %x\n", m_dirPaths.top().constData(), int(filters)); + m_nextDirShown = ShowDotDotDir; + return true; + } + if (m_nextDirShown == ShowDotDotDir) { + //printf("RESTING ON DOTDOT %s %x\n", m_dirPaths.top().constData(), int(filters)); + m_nextDirShown = DontShowDir; + return true; + } + m_currentDirShown = DontShowDir; + } + +#ifdef Q_OS_WIN + m_entry = &m_fileSearchResult; + if (m_bFirstSearchResult) { + m_bFirstSearchResult = false; + } else { + if (!FindNextFile(m_dirStructs.top(), m_entry)) + m_entry = 0; + } + + while (m_entry && isDotOrDotDot(m_entry->cFileName)) + if (!FindNextFile(m_dirStructs.top(), m_entry)) + m_entry = 0; + + if (!m_entry) { + m_dirPaths.pop(); + FindClose(m_dirStructs.pop()); + return false; + } + + if (m_entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + QByteArray ba = m_dirPaths.top(); + ba += '\\'; + ba += QString::fromWCharArray(m_entry->cFileName); + pushSubDirectory(ba); + } +#else + m_entry = ::readdir(m_dirStructs.top()); + while (m_entry && isDotOrDotDot(m_entry->d_name)) + m_entry = ::readdir(m_dirStructs.top()); + //return false; // further iteration possibly needed + //printf("READ %p %s\n", m_entry, m_entry ? m_entry->d_name : ""); + + if (!m_entry) { + m_dirPaths.pop(); + DIR *dir = m_dirStructs.pop(); + ::closedir(dir); + return false; // further iteration possibly needed + } + + const char *name = m_entry->d_name; + + QByteArray ba = m_dirPaths.top(); + ba += '/'; + ba += name; + struct stat st; + lstat(ba.constData(), &st); + + if (S_ISDIR(st.st_mode)) { + pushSubDirectory(ba); + return false; // further iteration possibly needed + } +#endif + return false; // further iteration possiblye needed +} + +/*! + \internal + */ +bool QFileSystemIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo) +{ + // If we're doing flat iteration, we're done. + if (!(iteratorFlags & QFileSystemIterator::Subdirectories)) + return false; + + // Never follow non-directory entries + if (!fileInfo.isDir()) + return false; + + + // Never follow . and .. + if (fileInfo.fileName() == QLatin1String(".") || fileInfo.fileName() == QLatin1String("..")) + return false; + + + // Check symlinks + if (fileInfo.isSymLink() && !(iteratorFlags & QFileSystemIterator::FollowSymlinks)) { + // Follow symlinks only if FollowSymlinks was passed + return false; + } + + // Stop link loops + if (visitedLinks.contains(fileInfo.canonicalFilePath())) + return false; + + return true; +} + + +/*! + \internal + + This convenience function implements the iterator's filtering logics and + applies then to the current directory entry. + + It returns true if the current entry matches the filters (i.e., the + current entry will be returned as part of the directory iteration); + otherwise, false is returned. +*/ +#if 0 +bool QFileSystemIteratorPrivate::matchesFilters(const QAbstractFileEngineIterator *it) const +{ + const bool filterPermissions = ((filters & QDir::PermissionMask) + && (filters & QDir::PermissionMask) != QDir::PermissionMask); + const bool skipDirs = !(filters & (QDir::Dirs | QDir::AllDirs)); + const bool skipFiles = !(filters & QDir::Files); + const bool skipSymlinks = (filters & QDir::NoSymLinks); + const bool doReadable = !filterPermissions || (filters & QDir::Readable); + const bool doWritable = !filterPermissions || (filters & QDir::Writable); + const bool doExecutable = !filterPermissions || (filters & QDir::Executable); + const bool includeHidden = (filters & QDir::Hidden); + const bool includeSystem = (filters & QDir::System); + +#ifndef QT_NO_REGEXP + // Prepare name filters + QList<QRegExp> regexps; + bool hasNameFilters = !nameFilters.isEmpty() && !(nameFilters.contains(QLatin1String("*"))); + if (hasNameFilters) { + for (int i = 0; i < nameFilters.size(); ++i) { + regexps << QRegExp(nameFilters.at(i), + (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive, + QRegExp::Wildcard); + } + } +#endif + + QString fileName = it->currentFileName(); + if (fileName.isEmpty()) { + // invalid entry + return false; + } + + QFileInfo fi = it->currentFileInfo(); + QString filePath = it->currentFilePath(); + +#ifndef QT_NO_REGEXP + // Pass all entries through name filters, except dirs if the AllDirs + // filter is passed. + if (hasNameFilters && !((filters & QDir::AllDirs) && fi.isDir())) { + bool matched = false; + for (int i = 0; i < regexps.size(); ++i) { + if (regexps.at(i).exactMatch(fileName)) { + matched = true; + break; + } + } + if (!matched) + return false; + } +#endif + + bool dotOrDotDot = (fileName == QLatin1String(".") || fileName == QLatin1String("..")); + if ((filters & QDir::NoDotAndDotDot) && dotOrDotDot) + return false; + + bool isHidden = !dotOrDotDot && fi.isHidden(); + if (!includeHidden && isHidden) + return false; + + bool isSystem = (!fi.isFile() && !fi.isDir() && !fi.isSymLink()) + || (!fi.exists() && fi.isSymLink()); + if (!includeSystem && isSystem) + return false; + + bool alwaysShow = (filters & QDir::TypeMask) == 0 + && ((isHidden && includeHidden) + || (includeSystem && isSystem)); + + // Skip files and directories + if ((filters & QDir::AllDirs) == 0 && skipDirs && fi.isDir()) { + if (!alwaysShow) + return false; + } + + if ((skipFiles && (fi.isFile() || !fi.exists())) + || (skipSymlinks && fi.isSymLink())) { + if (!alwaysShow) + return false; + } + + if (filterPermissions + && ((doReadable && !fi.isReadable()) + || (doWritable && !fi.isWritable()) + || (doExecutable && !fi.isExecutable()))) { + return false; + } + + if (!includeSystem && !dotOrDotDot && ((fi.exists() && !fi.isFile() && !fi.isDir() && !fi.isSymLink()) + || (!fi.exists() && fi.isSymLink()))) { + return false; + } + + return true; +} +#endif + +/*! + Constructs a QFileSystemIterator that can iterate over \a dir's entrylist, using + \a dir's name filters and regular filters. You can pass options via \a + flags to decide how the directory should be iterated. + + By default, \a flags is NoIteratorFlags, which provides the same behavior + as in QDir::entryList(). + + The sorting in \a dir is ignored. + + \sa atEnd(), next(), IteratorFlags +*/ +QFileSystemIterator::QFileSystemIterator(const QDir &dir, IteratorFlags flags) + : d(new QFileSystemIteratorPrivate(dir.path(), dir.nameFilters(), dir.filter(), flags)) +{ + d->q = this; +} + +/*! + Constructs a QFileSystemIterator that can iterate over \a path, with no name + filtering and \a filters for entry filtering. You can pass options via \a + flags to decide how the directory should be iterated. + + By default, \a filters is QDir::NoFilter, and \a flags is NoIteratorFlags, + which provides the same behavior as in QDir::entryList(). + + \sa atEnd(), next(), IteratorFlags +*/ +QFileSystemIterator::QFileSystemIterator(const QString &path, QDir::Filters filters, IteratorFlags flags) + : d(new QFileSystemIteratorPrivate(path, QStringList(QLatin1String("*")), filters, flags)) +{ + d->q = this; +} + +/*! + Constructs a QFileSystemIterator that can iterate over \a path. You can pass + options via \a flags to decide how the directory should be iterated. + + By default, \a flags is NoIteratorFlags, which provides the same behavior + as in QDir::entryList(). + + \sa atEnd(), next(), IteratorFlags +*/ +QFileSystemIterator::QFileSystemIterator(const QString &path, IteratorFlags flags) + : d(new QFileSystemIteratorPrivate(path, QStringList(QLatin1String("*")), QDir::NoFilter, flags)) +{ + d->q = this; +} + +/*! + Constructs a QFileSystemIterator that can iterate over \a path, using \a + nameFilters and \a filters. You can pass options via \a flags to decide + how the directory should be iterated. + + By default, \a flags is NoIteratorFlags, which provides the same behavior + as QDir::entryList(). + + \sa atEnd(), next(), IteratorFlags +*/ +QFileSystemIterator::QFileSystemIterator(const QString &path, const QStringList &nameFilters, + QDir::Filters filters, IteratorFlags flags) + : d(new QFileSystemIteratorPrivate(path, nameFilters, filters, flags)) +{ + d->q = this; +} + +/*! + Destroys the QFileSystemIterator. +*/ +QFileSystemIterator::~QFileSystemIterator() +{ + delete d; +} + +/*! + Advances the iterator to the next entry, and returns the file path of this + new entry. If atEnd() returns true, this function does nothing, and + returns a null QString. + + You can call fileName() or filePath() to get the current entry file name + or path, or fileInfo() to get a QFileInfo for the current entry. + + \sa hasNext(), fileName(), filePath(), fileInfo() +*/ +void QFileSystemIterator::next() +{ + d->advance(); +} + +/*! + Returns true if there is at least one more entry in the directory; + otherwise, false is returned. + + \sa next(), fileName(), filePath(), fileInfo() +*/ +bool QFileSystemIterator::atEnd() const +{ + return d->atEnd(); +} + +/*! + Returns the file name for the current directory entry, without the path + prepended. If the current entry is invalid (i.e., isValid() returns + false), a null QString is returned. + + This function is provided for the convenience when iterating single + directories. For recursive iteration, you should call filePath() or + fileInfo() instead. + + \sa filePath(), fileInfo() +*/ +QString QFileSystemIterator::fileName() const +{ + if (d->atEnd() || !d->m_entry) + return QString(); + if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDir) + return QString(); + if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDir) + return QLatin1String("@"); + if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir) + return QLatin1String("@@"); +#ifdef Q_OS_WIN + return QString::fromWCharArray(d->m_entry->cFileName); +#else + return QString::fromLocal8Bit(d->m_entry->d_name); +#endif +} + +/*! + Returns the full file path for the current directory entry. If the current + entry is invalid (i.e., isValid() returns false), a null QString is + returned. + + \sa fileInfo(), fileName() +*/ +QString QFileSystemIterator::filePath() const +{ + if (d->atEnd()) + return QString(); + QByteArray ba = d->m_dirPaths.top(); + if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDir) + ba += "/."; + else if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir) + ba += "/.."; + else if (d->m_entry) { + ba += '/'; +#ifdef Q_OS_WIN + ba += QString::fromWCharArray(d->m_entry->cFileName); +#else + ba += d->m_entry->d_name; +#endif + } + return QString::fromLocal8Bit(ba); +} + +/*! + Returns a QFileInfo for the current directory entry. If the current entry + is invalid (i.e., isValid() returns false), a null QFileInfo is returned. + + \sa filePath(), fileName() +*/ +QFileInfo QFileSystemIterator::fileInfo() const +{ + return QFileInfo(filePath()); +} + +/*! + Returns the base directory of the iterator. +*/ +QString QFileSystemIterator::path() const +{ + return QString::fromLocal8Bit(d->m_dirPaths.top()); +} + +QT_END_NAMESPACE diff --git a/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h new file mode 100644 index 0000000..4aad3a1 --- /dev/null +++ b/tests/benchmarks/corelib/io/qdiriterator/qfilesystemiterator.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILESYSTEMITERATOR_H +#define QFILESYSTEMITERATOR_H + +#include <QtCore/qdir.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QFileSystemIteratorPrivate; +class //Q_CORE_EXPORT +QFileSystemIterator +{ +public: + enum IteratorFlag { + NoIteratorFlags = 0x0, + FollowSymlinks = 0x1, + Subdirectories = 0x2 + }; + Q_DECLARE_FLAGS(IteratorFlags, IteratorFlag) + + QFileSystemIterator(const QDir &dir, IteratorFlags flags = NoIteratorFlags); + QFileSystemIterator(const QString &path, + IteratorFlags flags = NoIteratorFlags); + QFileSystemIterator(const QString &path, + QDir::Filters filter, + IteratorFlags flags = NoIteratorFlags); + QFileSystemIterator(const QString &path, + const QStringList &nameFilters, + QDir::Filters filters = QDir::NoFilter, + IteratorFlags flags = NoIteratorFlags); + + virtual ~QFileSystemIterator(); + + void next(); + bool atEnd() const; + + QString fileName() const; + QString filePath() const; + QFileInfo fileInfo() const; + QString path() const; + +private: + Q_DISABLE_COPY(QFileSystemIterator) + + QFileSystemIteratorPrivate *d; + friend class QDir; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QFileSystemIterator::IteratorFlags) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/tests/benchmarks/corelib/io/qfile/main.cpp b/tests/benchmarks/corelib/io/qfile/main.cpp new file mode 100644 index 0000000..103b77c --- /dev/null +++ b/tests/benchmarks/corelib/io/qfile/main.cpp @@ -0,0 +1,675 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDebug> +#include <QTemporaryFile> +#include <QFSFileEngine> +#include <QString> +#include <QDirIterator> + +#include <qtest.h> + +#include <stdio.h> + +#ifdef Q_OS_WIN +# include <windows.h> +# include <atlbase.h> +#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[] = {TF_SIZE*0.52, + TF_SIZE*0.23, + TF_SIZE*0.73, + TF_SIZE*0.77, + TF_SIZE*0.80, + TF_SIZE*0.12, + TF_SIZE*0.53, + TF_SIZE*0.21, + TF_SIZE*0.27, + 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<factor; ++row) { + // tmpFile.write(QByteArray().fill('0'+row%('0'-'z'), 80)); + // tmpFile.write("\n"); + //} + tmpFile.seek(factor*80); + tmpFile.putChar('\n'); + tmpFile.close(); + // let IO settle + QTest::qSleep(2000); +} + +void tst_qfile::initTestCase() +{ +} + +void tst_qfile::cleanupTestCase() +{ +} + +void tst_qfile::readBigFile_QFile() { readBigFile(); } +void tst_qfile::readBigFile_QFSFileEngine() { readBigFile(); } +void tst_qfile::readBigFile_posix() { readBigFile(); } +void tst_qfile::readBigFile_Win32() { readBigFile(); } + +void tst_qfile::readBigFile_QFile_data() +{ + readBigFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); + readBigFile_data(QFileBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readBigFile_data(QFileBenchmark, QIODevice::Text, QIODevice::NotOpen); + readBigFile_data(QFileBenchmark, QIODevice::Text, QIODevice::Unbuffered); + +} + +void tst_qfile::readBigFile_QFSFileEngine_data() +{ + readBigFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); + readBigFile_data(QFSFileEngineBenchmark, QIODevice::NotOpen, QIODevice::Unbuffered); + readBigFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::NotOpen); + readBigFile_data(QFSFileEngineBenchmark, QIODevice::Text, QIODevice::Unbuffered); +} + +void tst_qfile::readBigFile_posix_data() +{ + readBigFile_data(PosixBenchmark, QIODevice::NotOpen, QIODevice::NotOpen); +} + +void tst_qfile::readBigFile_Win32_data() +{ + readBigFile_data(Win32Benchmark, QIODevice::NotOpen, QIODevice::NotOpen); +} + + +void tst_qfile::readBigFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b) +{ + QTest::addColumn<tst_qfile::BenchmarkType>("testType"); + QTest::addColumn<int>("blockSize"); + QTest::addColumn<QFile::OpenModeFlag>("textMode"); + QTest::addColumn<QFile::OpenModeFlag>("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<bs_entries; ++i) + QTest::newRow((QString("BS: %1, Flags: %2" )).arg(bs[i]).arg(flagstring).toLatin1().constData()) << type << bs[i] << t << b; +} + +void tst_qfile::readBigFile() +{ + QFETCH(tst_qfile::BenchmarkType, testType); + QFETCH(int, blockSize); + QFETCH(QFile::OpenModeFlag, textMode); + QFETCH(QFile::OpenModeFlag, bufferedMode); + +#ifndef Q_OS_WIN + if (testType == Win32Benchmark) + QSKIP("This is Windows only benchmark.", SkipSingle); +#endif + + char *buffer = new char[BUFSIZE]; + createFile(); + fillFile(); + + switch (testType) { + case(QFileBenchmark): { + QFile file(filename); + file.open(QIODevice::ReadOnly|textMode|bufferedMode); + QBENCHMARK { + while(!file.atEnd()) + file.read(blockSize); + file.reset(); + } + file.close(); + } + break; + case(QFSFileEngineBenchmark): { + QFSFileEngine fse(filename); + fse.open(QIODevice::ReadOnly|textMode|bufferedMode); + QBENCHMARK { + //qWarning() << fse.supportsExtension(QAbstractFileEngine::AtEndExtension); + while(fse.read(buffer, blockSize)); + fse.seek(0); + } + fse.close(); + } + break; + case(PosixBenchmark): { + QByteArray data = filename.toLocal8Bit(); + const char* cfilename = data.constData(); + FILE* cfile = ::fopen(cfilename, "rb"); + QBENCHMARK { + while(!feof(cfile)) + ::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 + 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); + SetFilePointer(hndl, 0, NULL, FILE_BEGIN); + } + delete[] nativeBuffer; + CloseHandle(hndl); +#else + QFAIL("Not running on a non-Windows platform!"); +#endif + } + break; + } + + removeFile(); + delete[] buffer; +} + +void tst_qfile::seek_data() +{ + QTest::addColumn<tst_qfile::BenchmarkType>("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<tst_qfile::BenchmarkType>("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<tst_qfile::BenchmarkType>("testType"); + QTest::addColumn<int>("blockSize"); + QTest::addColumn<QFile::OpenModeFlag>("textMode"); + QTest::addColumn<QFile::OpenModeFlag>("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<bs_entries; ++i) + QTest::newRow((QString("BS: %1, Flags: %2" )).arg(bs[i]).arg(flagstring).toLatin1().constData()) << type << bs[i] << t << b; + +} + +void tst_qfile::createSmallFiles() +{ + QDir dir = QDir::temp(); + dir.mkdir("tst"); + dir.cd("tst"); + tmpDirName = dir.absolutePath(); + +#ifdef Q_OS_SYMBIAN + for (int i = 0; i < 100; ++i) +#else + for (int i = 0; i < 1000; ++i) +#endif + { + QFile f(tmpDirName+"/"+QString::number(i)); + f.open(QIODevice::WriteOnly); + f.seek(511); + f.putChar('\n'); + f.close(); + } +} + +void tst_qfile::removeSmallFiles() +{ + QDirIterator it(tmpDirName, QDirIterator::FollowSymlinks); + while (it.hasNext()) + QFile::remove(it.next()); + QDir::temp().rmdir("tst"); +} + + +void tst_qfile::readSmallFiles() +{ + QFETCH(tst_qfile::BenchmarkType, testType); + QFETCH(int, blockSize); + QFETCH(QFile::OpenModeFlag, textMode); + QFETCH(QFile::OpenModeFlag, bufferedMode); + +#ifndef Q_OS_WIN + if (testType == Win32Benchmark) + QSKIP("This is Windows only benchmark.", SkipSingle); +#endif + + createSmallFiles(); + + QDir dir(tmpDirName); + const QStringList files = dir.entryList(QDir::NoDotAndDotDot|QDir::NoSymLinks|QDir::Files); + char *buffer = new char[BUFSIZE]; + + switch (testType) { + case(QFileBenchmark): { + QList<QFile*> 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<QFSFileEngine*> 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<FILE*> 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" diff --git a/tests/benchmarks/corelib/io/qfile/qfile.pro b/tests/benchmarks/corelib/io/qfile/qfile.pro new file mode 100644 index 0000000..99505c3 --- /dev/null +++ b/tests/benchmarks/corelib/io/qfile/qfile.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qfile +QT -= gui +win32: DEFINES+= _CRT_SECURE_NO_WARNINGS + +SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/io/qfileinfo/main.cpp b/tests/benchmarks/corelib/io/qfileinfo/main.cpp new file mode 100644 index 0000000..025787f --- /dev/null +++ b/tests/benchmarks/corelib/io/qfileinfo/main.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QDebug> +#include <qtest.h> +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> +#include <QtCore/QFileInfo> + +#include "private/qfsfileengine_p.h" + +class qfileinfo : public QObject +{ + Q_OBJECT +private slots: + void canonicalFileNamePerformance(); + + void initTestCase(); + void cleanupTestCase(); +public: + qfileinfo() : QObject() {}; +}; + +void qfileinfo::initTestCase() +{ +} + +void qfileinfo::cleanupTestCase() +{ +} + +void qfileinfo::canonicalFileNamePerformance() +{ + QString appPath = QCoreApplication::applicationFilePath(); + QFSFileEnginePrivate::canonicalized(appPath); // warmup + QFSFileEnginePrivate::canonicalized(appPath); // more warmup + QBENCHMARK { + for (int i = 0; i < 5000; i++) { + QFSFileEnginePrivate::canonicalized(appPath); + } + } +} + +QTEST_MAIN(qfileinfo) + +#include "main.moc" diff --git a/tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro b/tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro new file mode 100644 index 0000000..295cb50 --- /dev/null +++ b/tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro @@ -0,0 +1,12 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = qfileinfo +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui + +CONFIG += release + +# Input +SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/io/qiodevice/main.cpp b/tests/benchmarks/corelib/io/qiodevice/main.cpp new file mode 100644 index 0000000..4af697c --- /dev/null +++ b/tests/benchmarks/corelib/io/qiodevice/main.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QDebug> +#include <QIODevice> +#include <QFile> +#include <QString> + +#include <qtest.h> + + +class tst_qiodevice : public QObject +{ + Q_OBJECT +private slots: + void read_old(); + void read_old_data() { read_data(); } + //void read_new(); + //void read_new_data() { read_data(); } +private: + void read_data(); +}; + + +void tst_qiodevice::read_data() +{ + QTest::addColumn<qint64>("size"); + QTest::newRow("10k") << qint64(10 * 1024); + QTest::newRow("100k") << qint64(100 * 1024); + QTest::newRow("1000k") << qint64(1000 * 1024); + QTest::newRow("10000k") << qint64(10000 * 1024); +#ifndef Q_OS_SYMBIAN // Symbian devices don't (yet) have enough available RAM to run these + QTest::newRow("100000k") << qint64(100000 * 1024); + QTest::newRow("1000000k") << qint64(1000000 * 1024); +#endif +} + +void tst_qiodevice::read_old() +{ + QFETCH(qint64, size); + + QString name = "tmp" + QString::number(size); + + { + QFile file(name); + file.open(QIODevice::WriteOnly); + file.seek(size); + file.write("x", 1); + file.close(); + } + + QBENCHMARK { + QFile file(name); + file.open(QIODevice::ReadOnly); + QByteArray ba; + qint64 s = size - 1024; + file.seek(512); + ba = file.read(s); // crash happens during this read / assignment operation + } + + { + QFile file(name); + file.remove(); + } +} + + +QTEST_MAIN(tst_qiodevice) + +#include "main.moc" diff --git a/tests/benchmarks/corelib/io/qiodevice/qiodevice.pro b/tests/benchmarks/corelib/io/qiodevice/qiodevice.pro new file mode 100755 index 0000000..749a4d6 --- /dev/null +++ b/tests/benchmarks/corelib/io/qiodevice/qiodevice.pro @@ -0,0 +1,13 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qiodevice +TARGET.EPOCHEAPSIZE = 0x100000 0x2000000 +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui + +CONFIG += release + +# Input +SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/io/qtemporaryfile/main.cpp b/tests/benchmarks/corelib/io/qtemporaryfile/main.cpp new file mode 100644 index 0000000..8b71189 --- /dev/null +++ b/tests/benchmarks/corelib/io/qtemporaryfile/main.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QDebug> +#include <QIODevice> +#include <QFile> +#include <QString> +#include <QTemporaryFile> +#include <qtest.h> + + +class tst_qtemporaryfile : public QObject +{ + Q_OBJECT +private slots: + void openclose_data(); + void openclose(); + void readwrite_data() { openclose_data(); } + void readwrite(); + +private: +}; + +void tst_qtemporaryfile::openclose_data() +{ + QTest::addColumn<qint64>("amount"); + QTest::newRow("100") << qint64(100); + QTest::newRow("1000") << qint64(1000); + QTest::newRow("10000") << qint64(10000); +} + +void tst_qtemporaryfile::openclose() +{ + QFETCH(qint64, amount); + + QBENCHMARK { + for (qint64 i = 0; i < amount; ++i) { + QTemporaryFile file; + file.open(); + file.close(); + } + } +} + +void tst_qtemporaryfile::readwrite() +{ + QFETCH(qint64, amount); + + const int dataSize = 4096; + QByteArray data; + data.fill('a', dataSize); + QBENCHMARK { + for (qint64 i = 0; i < amount; ++i) { + QTemporaryFile file; + file.open(); + file.write(data); + file.seek(0); + file.read(dataSize); + file.close(); + } + } +} + +QTEST_MAIN(tst_qtemporaryfile) + +#include "main.moc" diff --git a/tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro b/tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro new file mode 100644 index 0000000..c1b04f4 --- /dev/null +++ b/tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro @@ -0,0 +1,12 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qtemporaryfile +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui + +CONFIG += release + +# Input +SOURCES += main.cpp |