File indexing completed on 2024-05-12 05:46:36

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