File indexing completed on 2024-06-23 10:37:26

0001 /*
0002     SPDX-FileCopyrightText: 2014 Frank Reininghaus <frank78ac@googlemail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <kio/udsentry.h>
0008 
0009 #include <QTest>
0010 
0011 /**
0012  * This benchmarks tests four typical uses of UDSEntry:
0013  *
0014  * (a)  Store data in UDSEntries using
0015  *      UDSEntry::insert(uint, const QString&) and
0016  *      UDSEntry::insert(uint, long long),
0017  *      and append the entries to a UDSEntryList.
0018  *
0019  * (b)  Read data from UDSEntries in a UDSEntryList using
0020  *      UDSEntry::stringValue(uint) and UDSEntry::numberValue(uint).
0021  *
0022  * (c)  Save a UDSEntryList in a QDataStream.
0023  *
0024  * (d)  Load a UDSEntryList from a QDataStream.
0025  *
0026  * This is done for two different data sets:
0027  *
0028  * 1.   UDSEntries containing the entries which are provided by kio_file.
0029  *
0030  * 2.   UDSEntries with a larger number of "fields".
0031  */
0032 
0033 // The following constants control the number of UDSEntries that are considered
0034 // in each test, and the number of extra "fields" that are used for large UDSEntries.
0035 const int numberOfSmallUDSEntries = 100 * 1000;
0036 const int numberOfLargeUDSEntries = 5 * 1000;
0037 const int extraFieldsForLargeUDSEntries = 40;
0038 
0039 class UDSEntryBenchmark : public QObject
0040 {
0041     Q_OBJECT
0042 
0043 public:
0044     UDSEntryBenchmark();
0045 
0046 private Q_SLOTS:
0047     void createSmallEntries();
0048     void createLargeEntries();
0049     void readFieldsFromSmallEntries();
0050     void readFieldsFromLargeEntries();
0051     void saveSmallEntries();
0052     void saveLargeEntries();
0053     void loadSmallEntries();
0054     void loadLargeEntries();
0055 
0056 private:
0057     KIO::UDSEntryList m_smallEntries;
0058     KIO::UDSEntryList m_largeEntries;
0059     QByteArray m_savedSmallEntries;
0060     QByteArray m_savedLargeEntries;
0061 
0062     QVector<uint> m_fieldsForLargeEntries;
0063 };
0064 
0065 UDSEntryBenchmark::UDSEntryBenchmark()
0066 {
0067     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_SIZE);
0068     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_SIZE_LARGE);
0069     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_USER);
0070     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_ICON_NAME);
0071     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_GROUP);
0072     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_NAME);
0073     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_LOCAL_PATH);
0074     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_HIDDEN);
0075     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_ACCESS);
0076     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_MODIFICATION_TIME);
0077     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_ACCESS_TIME);
0078     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_CREATION_TIME);
0079     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_FILE_TYPE);
0080     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_LINK_DEST);
0081     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_URL);
0082     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_MIME_TYPE);
0083     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_GUESSED_MIME_TYPE);
0084     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_XML_PROPERTIES);
0085     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_EXTENDED_ACL);
0086     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_ACL_STRING);
0087     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_DEFAULT_ACL_STRING);
0088     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_DISPLAY_NAME);
0089     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_TARGET_URL);
0090     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_DISPLAY_TYPE);
0091     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_ICON_OVERLAY_NAMES);
0092     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_COMMENT);
0093     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_DEVICE_ID);
0094     m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_INODE);
0095 
0096     for (int i = 0; i < extraFieldsForLargeUDSEntries; ++i) {
0097         m_fieldsForLargeEntries.append(KIO::UDSEntry::UDS_EXTRA + i);
0098     }
0099 }
0100 
0101 void UDSEntryBenchmark::createSmallEntries()
0102 {
0103     m_smallEntries.clear();
0104     m_smallEntries.reserve(numberOfSmallUDSEntries);
0105 
0106     const QString user = QStringLiteral("user");
0107     const QString group = QStringLiteral("group");
0108 
0109     QVector<QString> names(numberOfSmallUDSEntries);
0110     for (int i = 0; i < numberOfSmallUDSEntries; ++i) {
0111         names[i] = QString::number(i);
0112     }
0113 
0114     QBENCHMARK_ONCE {
0115         for (int i = 0; i < numberOfSmallUDSEntries; ++i) {
0116             KIO::UDSEntry entry;
0117             entry.reserve(8);
0118             entry.fastInsert(KIO::UDSEntry::UDS_NAME, names[i]);
0119             entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, i);
0120             entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, i);
0121             entry.fastInsert(KIO::UDSEntry::UDS_SIZE, i);
0122             entry.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, i);
0123             entry.fastInsert(KIO::UDSEntry::UDS_USER, user);
0124             entry.fastInsert(KIO::UDSEntry::UDS_GROUP, group);
0125             entry.fastInsert(KIO::UDSEntry::UDS_ACCESS_TIME, i);
0126             m_smallEntries.append(entry);
0127         }
0128     }
0129 
0130     Q_ASSERT(m_smallEntries.count() == numberOfSmallUDSEntries);
0131 }
0132 
0133 void UDSEntryBenchmark::createLargeEntries()
0134 {
0135     m_largeEntries.clear();
0136     m_largeEntries.reserve(numberOfLargeUDSEntries);
0137 
0138     QVector<QString> names(numberOfLargeUDSEntries);
0139     for (int i = 0; i < numberOfLargeUDSEntries; ++i) {
0140         names[i] = QString::number(i);
0141     }
0142 
0143     QBENCHMARK_ONCE {
0144         for (int i = 0; i < numberOfLargeUDSEntries; ++i) {
0145             KIO::UDSEntry entry;
0146             entry.reserve(m_fieldsForLargeEntries.count());
0147             for (uint field : std::as_const(m_fieldsForLargeEntries)) {
0148                 if (field & KIO::UDSEntry::UDS_STRING) {
0149                     entry.fastInsert(field, names[i]);
0150                 } else {
0151                     entry.fastInsert(field, i);
0152                 }
0153             }
0154             m_largeEntries.append(entry);
0155         }
0156     }
0157 
0158     Q_ASSERT(m_largeEntries.count() == numberOfLargeUDSEntries);
0159 }
0160 
0161 void UDSEntryBenchmark::readFieldsFromSmallEntries()
0162 {
0163     // Create the entries if they do not exist yet.
0164     if (m_smallEntries.isEmpty()) {
0165         createSmallEntries();
0166     }
0167 
0168     const QString user = QStringLiteral("user");
0169     const QString group = QStringLiteral("group");
0170 
0171     QBENCHMARK {
0172         long long i = 0;
0173         long long entrySum = 0;
0174 
0175         for (const KIO::UDSEntry &entry : std::as_const(m_smallEntries)) {
0176             entrySum += entry.count();
0177             /* clang-format off */
0178             if (entry.stringValue(KIO::UDSEntry::UDS_NAME).toInt() == i
0179                 && entry.numberValue(KIO::UDSEntry::UDS_FILE_TYPE) == i
0180                 && entry.numberValue(KIO::UDSEntry::UDS_ACCESS) == i
0181                 && entry.numberValue(KIO::UDSEntry::UDS_SIZE) == i
0182                 && entry.numberValue(KIO::UDSEntry::UDS_MODIFICATION_TIME) == i
0183                 && entry.stringValue(KIO::UDSEntry::UDS_USER) == user
0184                 && entry.stringValue(KIO::UDSEntry::UDS_GROUP) == group
0185                 && entry.numberValue(KIO::UDSEntry::UDS_ACCESS_TIME) == i) { /* clang-format on */
0186                 ++i;
0187             }
0188         }
0189 
0190         QCOMPARE(i, numberOfSmallUDSEntries);
0191         QCOMPARE(entrySum, numberOfSmallUDSEntries * 8);
0192     }
0193 }
0194 
0195 void UDSEntryBenchmark::readFieldsFromLargeEntries()
0196 {
0197     // Create the entries if they do not exist yet.
0198     if (m_largeEntries.isEmpty()) {
0199         createLargeEntries();
0200     }
0201 
0202     QBENCHMARK_ONCE {
0203         long long i = 0;
0204         long long fieldSum = 0;
0205 
0206         for (const KIO::UDSEntry &entry : std::as_const(m_largeEntries)) {
0207             for (uint field : std::as_const(m_fieldsForLargeEntries)) {
0208                 if (field & KIO::UDSEntry::UDS_STRING) {
0209                     if (entry.stringValue(field).toInt() == i) {
0210                         ++fieldSum;
0211                     }
0212                 } else if (entry.numberValue(field) == i) {
0213                     ++fieldSum;
0214                 }
0215             }
0216             ++i;
0217         }
0218 
0219         QCOMPARE(fieldSum, m_fieldsForLargeEntries.count() * m_largeEntries.count());
0220     }
0221 }
0222 
0223 void UDSEntryBenchmark::saveSmallEntries()
0224 {
0225     // Create the entries if they do not exist yet.
0226     if (m_smallEntries.isEmpty()) {
0227         createSmallEntries();
0228     }
0229 
0230     m_savedSmallEntries.clear();
0231 
0232     QBENCHMARK_ONCE {
0233         QDataStream stream(&m_savedSmallEntries, QIODevice::WriteOnly);
0234         stream << m_smallEntries;
0235     }
0236 }
0237 
0238 void UDSEntryBenchmark::saveLargeEntries()
0239 {
0240     // Create the entries if they do not exist yet.
0241     if (m_smallEntries.isEmpty()) {
0242         createLargeEntries();
0243     }
0244 
0245     m_savedLargeEntries.clear();
0246 
0247     QBENCHMARK_ONCE {
0248         QDataStream stream(&m_savedLargeEntries, QIODevice::WriteOnly);
0249         stream << m_largeEntries;
0250     }
0251 }
0252 void UDSEntryBenchmark::loadSmallEntries()
0253 {
0254     // Save the entries if that has not been done yet.
0255     if (m_savedSmallEntries.isEmpty()) {
0256         saveSmallEntries();
0257     }
0258 
0259     QDataStream stream(m_savedSmallEntries);
0260     KIO::UDSEntryList entries;
0261 
0262     QBENCHMARK_ONCE {
0263         stream >> entries;
0264     }
0265 
0266     QCOMPARE(entries, m_smallEntries);
0267 }
0268 
0269 void UDSEntryBenchmark::loadLargeEntries()
0270 {
0271     // Save the entries if that has not been done yet.
0272     if (m_savedLargeEntries.isEmpty()) {
0273         saveLargeEntries();
0274     }
0275 
0276     QDataStream stream(m_savedLargeEntries);
0277     KIO::UDSEntryList entries;
0278 
0279     QBENCHMARK_ONCE {
0280         stream >> entries;
0281     }
0282 
0283     QCOMPARE(entries, m_largeEntries);
0284 }
0285 
0286 QTEST_MAIN(UDSEntryBenchmark)
0287 
0288 #include "udsentry_benchmark.moc"