使用QVector<QPair<QPair<QString, QString>、QString的性能问题>>

Performance problems using QVector<QPair<QPair<QString, QString>, QString>>

我在使用 QVector<QPair<QPair<QString, QString>, QString>> 实例时遇到严重的性能问题。

假设我有一个 class EmojiList,它除了保存这个填充了大约 4000 个表情符号及其各自的简称和类别的向量之外什么都不做:

emojilist.h

#include <QVector>

class EmojiList {
public:
    static const QVector<QPair<QPair<QString, QString>, QString>>& list() {
        static EmojiList list;

        return list.emojiList;
    }

private:
    QVector<QPair<QPair<QString, QString>, QString>> emojiList {
        { { "‍‍‍", ":woman_woman_girl_girl:" }, "People & Body" },
        { { "‍‍‍", ":woman_woman_girl_boy:" }, "People & Body" },
        { { "‍‍‍", ":woman_woman_boy_boy:" }, "People & Body" },
        { { "‍‍‍", ":man_woman_girl_girl:" }, "People & Body" },
        { { "‍‍‍", ":man_woman_girl_boy:" }, "People & Body" },
        // ... ~ 4000 entries to come
    };

它在其他 class 中被引用( 复制)两次,并在 QAbstractListModel 子class 中直接在构造时查询:

emojilistmodel.h

#include "emojilist.h"

class EmojiListModel : public QAbstractTableModel
{
    Q_OBJECT

    // ...

private:
    const QVector<QPair<QPair<QString, QString>, QString>>& _emojiMap { EmojiList::list() };

当编译我的应用程序时,包括 emojilist.h,编译大约需要 1:20 分钟,没有 emojilist.h,需要 3.8 秒。

此外,启动应用程序比不包含 emojilist.h 时花费的时间长得多:不包含 emojilist.h 的启动时间为 4 秒,包含 emojilist.h 的启动时间为 3:40分钟.

如何优化我的代码以提高性能和速度?我应该使用不同于 QVector 的 class 还是应该切换到 QMap 或不同类型的容器?

也许在这种情况下也使用 Singleton 并不是一个好主意?

非常感谢。

我通过将表情符号列表解析外包到 .cpp 文件中,设法将编译时间减少到 3 秒:

emojilist.h

#include <QVector>

class EmojiList {
public:

    struct EmojiData {
        EmojiData(const QString& _code, const QString& _shortname, const QString& _category) :
            code(_code),
            shortname(_shortname),
            category(_category)
        {}

        QString code;
        QString shortname;
        QString category;
    };

    static const QVector<EmojiData>& list();

private:
    QVector<EmojiData> emojiList;

    void parseFromFile();
};

emojilist.cpp

#include "emojilist.h"

#include <QFile>
#include <QTextStream>

const QVector<EmojiList::EmojiData>& EmojiList::list()
{
    static EmojiList list;

    if (list.emojiList.isEmpty()) {
        list.parseFromFile();
    }

    return list.emojiList;
}

void EmojiList::parseFromFile()
{
    QFile emojiResource { ":/media/new_emoji.list" };

    if (emojiResource.open(QIODevice::ReadOnly)) {
        QTextStream in { &emojiResource };

        while (!in.atEnd()) {
            QStringList line { in.readLine().split(',') };
            emojiList.append({ line.at(0), line.at(1), line.at(2) });
        }
    }

    emojiResource.close();
}

然后在我的列表模型中检索它:

emojilistmodel.cpp

QVariant EmojiListModel::data(const QModelIndex &index, int role) const
{
    if (_emojiMap.isEmpty() || !index.isValid() || index.row() > _emojiMap.size()) {
        return QVariant();
    }

    switch (role) {
    case EmojiName:
        return _emojiMap.at(index.row()).shortname;
    case Emoji:
        return _emojiMap.at(index.row()).code;
    case EmojiCategory: {
        return _emojiMap.at(index.row()).category;
    }
    default:
        return QVariant();
    }
}

它工作得很好,但是启动仍然需要很长时间(5 分钟以上)。无论如何,这似乎是一个 QML-related 问题 所以我必须为此创建一个额外的问题。

非常感谢大家到目前为止的帮助。