diff options
author | Ahmad Samir <a.samirh78@gmail.com> | 2024-02-05 16:01:19 +0200 |
---|---|---|
committer | Ahmad Samir <a.samirh78@gmail.com> | 2024-02-29 16:35:57 +0200 |
commit | 5e9de279ac06f727aadf5dbfbce74d117ff00d28 (patch) | |
tree | 77dedb5c245f3da91173fdba4f0e63f037541691 | |
parent | c39a0d1e8956e042139ce3065681e4c5d07412f3 (diff) |
tst_bench_qdiriterator: add benchmark for QDirListing
Make the benchmarks more comparable:
- Store the QDir::Filters in one central var, this way it's the same in
all the call sites
- Add a `bool forceStat`, when true force calling stat(), either
explicitly in posix_helper(), or implicitly in Qt classes by e.g.
calling a QFileInfo method that would have to call system stat()
internally. Otherwise benchmarking readdir()/dirent showed bigger
times, which was mostly due to the explicit stat() calls, whereas we
can use dirent::d_type (on the platforms where it's available)
Drive by change: for std::filesystem::recursive_directory_iterator, set
skip_permission_denied option and use the non-throwing constructor.
Change-Id: Icf138a5dc41d32741c1be611d664b01008b2f3fe
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp | 79 |
1 files changed, 65 insertions, 14 deletions
diff --git a/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp b/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp index bf9dd4f6eb..d97cb5cc75 100644 --- a/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp +++ b/tests/benchmarks/corelib/io/qdiriterator/tst_bench_qdiriterator.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QDebug> #include <QDirIterator> +#include <QDirListing> #include <QString> #include <qplatformdefs.h> @@ -23,16 +24,30 @@ #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(); @@ -118,9 +133,20 @@ static int posix_helper(const char *dirpath) 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); - if (S_ISDIR(st.st_mode)) + isDir = S_ISDIR(st.st_mode); +#endif + + if (isDir) count += posix_helper(ba.constData()); } @@ -157,14 +183,12 @@ void tst_QDirIterator::diriterator() QBENCHMARK { int c = 0; - QDirIterator dir(dirpath, - //QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, - //QDir::AllEntries | QDir::Hidden, - QDir::Files, - QDirIterator::Subdirectories); + 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(), @@ -178,6 +202,28 @@ void tst_QDirIterator::diriterator() 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); @@ -189,14 +235,12 @@ void tst_QDirIterator::fsiterator() int c = 0; dump && printf("\n\n\n\n"); - QDirIteratorTest::QFileSystemIterator dir(dirpath, - //QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot, - //QDir::AllEntries | QDir::Hidden, - //QDir::Files | QDir::NoDotAndDotDot, - QDir::Files, - QDirIteratorTest::QFileSystemIterator::Subdirectories); + 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()), @@ -217,10 +261,17 @@ void tst_QDirIterator::stdRecursiveDirectoryIterator() 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 (auto obj : std::filesystem::recursive_directory_iterator(dirpath.data())) { - if (obj.is_directory()) + for (const auto &dirEntry : fs::recursive_directory_iterator( + dirpath.data(), fs::directory_options::skip_permission_denied, ec)) { + if (dirEntry.is_directory()) continue; c++; } |