前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >翻译 | QMap与QHash小基准

翻译 | QMap与QHash小基准

作者头像
Qt君
发布2019-09-18 16:44:05
8150
发布2019-09-18 16:44:05
举报
文章被收录于专栏:跟Qt君学编程

本文翻译自: https://woboq.com/blog/qmap_qhash_benchmark.html 作者: Olivier Goffart

  在我的Qt开发者日2012演示文稿(深入探讨QtCore)时,我做了一个比较QMap和QHash的基准。我认为在这篇简短的博客文章中分享结果会很不错。

在底层实现上

在Qt 4中QHash使用哈希表实现,而QMap使用跳跃表实现。

在Qt 5中,虽然容器的实现有所改变,但概念仍然相同。主要有以下区别:

  • QVector、QString和QByteArray现在共享相同的实现(QArrayData)。主要的区别是现在有一个偏移量,将来可能允许引用外部数据
  • QMap的实现已经完全改变了。它不再是跳跃表,而是一个红黑树。

基准

  基准测试很简单,并且在一秒钟内在循环中进行大量查找并计算迭代次数。 这不是真正科学严谨的。我们的目标只是展示曲线的形状。

结果

  在我的电脑上运行,gcc 4.7。越高越好。元素的数量是对数标度。对于QHash,人们应该期望它不随元素数量而变化,对于QMap,它应该是O(log N): 对数刻度上的直线。

Qt 4.8

  QMap的执行稍微慢于std::map。对于少于10个元素,QMap查找比QHash更快。

Qt 5

  将跳跃表更改为红黑树是一个好主意。与STL相比,Qt容器的性能基本相同。如果少于20个元素,QMap比QHash更快。

  如果比较Qt5和Qt4之间的数量,您会发现Qt5的性能更好。这可能与QString中的更改有关。

结论

  典型的规则是:仅当您需要对项进行排序,或者您知道您的映射中始终只有很少的项时,才使用QMap。


相关知识
  • 跳跃表:通过增加多级索引(会增加额外的空间)来提升插入与删除操作。
  • 红黑树:是一种特定类型的二叉树,进行插入和删除操作时通过特定操作保持二叉查找树的平衡。

附: 基准测试程序

代码语言:javascript
复制
/* Copyright 2013 Olivier Goffart <ogoffart@woboq.com>
http://woboq.com/blog/qmap_qhash_benchmark.html
*/

#include <QtCore/QtCore>
#include <unordered_map>

#ifndef CONTAINER
#error CONTAINER must be defined to QMap, QHash, std::map or std::unordered_map
#endif

namespace std{
/* std::hash specialization for QString so it can be used
  * as a key in std::unordered_map */
template<class Key> struct hash;
template<> struct hash<QString> {
    typedef QString Key;
    typedef uint result_type;
    inline uint operator()(const QString &s) const { return qHash(s); }
};
}


int main(int argc, char **argv) {
    if (argc < 2)
        qFatal("Missing number of element to add");

    QByteArray a = argv[1];
    uint num = a.toUInt();

    // creates an array of random keys
    QVector<QString> strs(num);
    for (int i=0; i < num; ++i)
        strs[i] = qvariant_cast<QString>(qrand());

    CONTAINER<QString, QString> c;
    for (uint i = 0; i < num; ++i) {
        QString &k = strs[i];
        c[k] = QString::number(i);
    }

    quint64 it = 0;
    const QString *arr = strs.constData();

    QElapsedTimer t;
    t.start();

    while (t.elapsed() < 1000) {
        const QString &k = arr[(++it)*797%num];
        c[k]; // perform a lookup
    }
    qDebug() << it/1000;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Qt君 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 在底层实现上
  • 基准
  • 结果
    • Qt 4.8
      • Qt 5
      • 结论
        • 相关知识
        • 附: 基准测试程序
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档