summaryrefslogtreecommitdiffstats
path: root/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp')
-rw-r--r--tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp287
1 files changed, 287 insertions, 0 deletions
diff --git a/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp b/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp
new file mode 100644
index 0000000000..66448bf838
--- /dev/null
+++ b/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp
@@ -0,0 +1,287 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+#include <QDebug>
+#include <QDirIterator>
+#include <QDirListing>
+#include <QString>
+#include <qplatformdefs.h>
+
+#ifdef Q_OS_WIN
+# include <qt_windows.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"
+
+#if QT_CONFIG(cxx17_filesystem)
+#include <filesystem>
+#endif
+
+using namespace Qt::StringLiterals;
+
+constexpr bool forceStat = false;
+
+class tst_QDirIterator : public QObject
+{
+ Q_OBJECT
+
+ void data();
+
+ const QDir::Filters dirFilters =
+ // QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot
+ QDir::AllEntries | QDir::Hidden
+ //QDir::Files | QDir::NoDotAndDotDot,
+ // QDir::Files,
+ ;
+
+private slots:
+ void posix();
+ void posix_data() { data(); }
+ void diriterator();
+ void diriterator_data() { data(); }
+ void dirlisting();
+ void dirlisting_data() { data(); }
+ void fsiterator();
+ void fsiterator_data() { data(); }
+ void stdRecursiveDirectoryIterator();
+ void stdRecursiveDirectoryIterator_data() { data(); }
+};
+
+void tst_QDirIterator::data()
+{
+ const char hereRelative[] = "tests/benchmarks/corelib/io/qdiriterator";
+ QByteArray dir(QT_TESTCASE_SOURCEDIR);
+ // qDebug("Source dir: %s", dir.constData());
+ dir.chop(sizeof(hereRelative)); // Counts the '\0', making up for the omitted leading '/'
+ // qDebug("Root dir: %s", dir.constData());
+
+ QTest::addColumn<QByteArray>("dirpath");
+ const QByteArray ba = dir + "/src/corelib";
+
+ if (!QFileInfo(QString::fromLocal8Bit(ba)).isDir())
+ QSKIP("Missing Qt directory");
+
+ QTest::newRow("corelib") << ba;
+ QTest::newRow("corelib/io") << (ba + "/io");
+}
+
+#ifdef Q_OS_WIN
+static int posix_helper(const wchar_t *dirpath, size_t length)
+{
+ int count = 0;
+ HANDLE hSearch;
+ WIN32_FIND_DATA fd;
+
+ wchar_t appendedPath[MAX_PATH];
+ Q_ASSERT(MAX_PATH > length + 3);
+ wcsncpy(appendedPath, dirpath, length);
+ wcscpy(appendedPath + length, L"\\*");
+ hSearch = FindFirstFile(appendedPath, &fd);
+
+ 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) {
+ // newLength will "point" to where we put a * earlier, so we overwrite that.
+ size_t newLength = length + 1; // "+ 1" for directory separator
+ Q_ASSERT(newLength + wcslen(fd.cFileName) + 1 < MAX_PATH); // "+ 1" for null-terminator
+ wcscpy(appendedPath + newLength, fd.cFileName);
+ newLength += wcslen(fd.cFileName);
+ count += posix_helper(appendedPath, newLength);
+ }
+ 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;
+ bool isDir = false;
+#if defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4)
+ isDir = entry->d_type == DT_DIR;
+ if (forceStat) {
+ QT_STATBUF st;
+ QT_LSTAT(ba.constData(), &st);
+ }
+#else // d_type not available >>> must stat() to see if it's a dir
+ QT_STATBUF st;
+ QT_LSTAT(ba.constData(), &st);
+ isDir = S_ISDIR(st.st_mode);
+#endif
+
+ if (isDir)
+ 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
+ wchar_t wPath[MAX_PATH];
+ const int end = path.toWCharArray(wPath);
+ count = posix_helper(wPath, end);
+#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, dirFilters, QDirIterator::Subdirectories);
+
+ while (dir.hasNext()) {
+ const auto fi = dir.nextFileInfo();
+ if (forceStat)
+ fi.size();
+ //printf("%s\n", qPrintable(dir.fileName()));
+ 0 && printf("%d %s\n",
+ fi.isDir(),
+ //qPrintable(fi.absoluteFilePath()),
+ //qPrintable(dir.path()),
+ qPrintable(fi.filePath()));
+ ++c;
+ }
+ count = c;
+ }
+ qDebug() << count;
+}
+
+void tst_QDirIterator::dirlisting()
+{
+ QFETCH(QByteArray, dirpath);
+
+ int count = 0;
+
+ QBENCHMARK {
+ int c = 0;
+
+ QDirListing dir(dirpath, dirFilters, QDirListing::IteratorFlag::Recursive);
+
+ for (const auto &dirEntry : dir) {
+ const auto path = dirEntry.filePath();
+ if (forceStat)
+ dirEntry.size();
+ ++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");
+ QDirIteratorTest::QFileSystemIterator dir(
+ dirpath, dirFilters, QDirIteratorTest::QFileSystemIterator::Subdirectories);
+
+ for (; !dir.atEnd(); dir.next()) {
+ if (forceStat)
+ dir.fileInfo().size();
+ dump && 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::stdRecursiveDirectoryIterator()
+{
+#if QT_CONFIG(cxx17_filesystem)
+ QFETCH(QByteArray, dirpath);
+
+ int count = 0;
+
+ namespace fs = std::filesystem;
+ std::error_code ec;
+
+ // Note that fs::recursive_directory_iterator may be calling stat() internally,
+ // that depends on the implementation. So the benchmark times might "seem" higher
+ // than the other methods in this source file.
+ QBENCHMARK {
+ int c = 0;
+ for (const auto &dirEntry : fs::recursive_directory_iterator(dirpath.data(), ec)) {
+ if (dirEntry.is_directory())
+ continue;
+ c++;
+ }
+ count = c;
+ }
+ qDebug() << count;
+#else
+ QSKIP("Not supported.");
+#endif
+}
+
+QTEST_MAIN(tst_QDirIterator)
+
+#include "tst_bench_qdiriterator.moc"