我的编程空间,编程开发者的网络收藏夹
学习永远不晚

go和c++的map性能对比

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

go和c++的map性能对比

Golang小白一枚,正在不断学习积累知识,现将学习到的知识记录一下,也是将我的所得分享给大家!而今天这篇文章《go和c++的map性能对比》带大家来了解一下##content_title##,希望对大家的知识积累有所帮助,从而弥补自己的不足,助力实战开发!


问题内容

我不明白为什么 golang 在这个操作上比 c++ 快了 10 倍,甚至 go 中的映射查找比 c++ 快了 3 倍。

这是 c++ 代码片段

#include <iostream>
#include <unordered_map>
#include <chrono>

std::chrono::nanoseconds elapsed(std::chrono::steady_clock::time_point start) {
    std::chrono::steady_clock::time_point now = std::chrono::high_resolution_clock::now();
    return std::chrono::duration_cast<std::chrono::nanoseconds>(now - start);
}
void make_map(int times) {
    std::unordered_map<double, double> hm;
    double c = 0.0;
    for (int i = 0; i < times; i++) {
        hm[c] = c + 10.0;
        c += 1.0;
    }
}

int main() {
    std::chrono::steady_clock::time_point start_time = std::chrono::high_resolution_clock::now();
    make_map(10000000);
    printf("elapsed %lld", elapsed(start_time).count());
}

这是 golang 代码片段:

func makeMap() {
    o := make(map[float64]float64)
    var i float64 = 0
    x := time.Now()
    for ; i <= 10000000; i++ {
        o[i] = i+ 10
    }
    TimeTrack(x)
}
func TimeTrack(start time.Time) {
    elapsed := time.Since(start)

    // Skip this function, and fetch the PC and file for its parent.
    pc, _, _, _ := runtime.Caller(1)

    // Retrieve a function object this functions parent.
    funcObj := runtime.FuncForPC(pc)

    // Regex to extract just the function name (and not the module path).
    runtimeFunc := regexp.MustCompile(`^.*\.(.*)$`)
    name := runtimeFunc.ReplaceAllString(funcObj.Name(), "$1")

    log.Println(fmt.Sprintf("%s took %s", name, elapsed))
}

我想知道的是如何优化c++以获得更好的性能。


解决方案


已更新以测量 cppgo 的类似操作。它在调用制图函数之前开始测量,并在函数返回时结束测量。两个版本都在地图中保留空间并返回创建的地图(从中打印几个数字)。

稍微修改了cpp

#include <iostream>
#include <unordered_map>
#include <chrono>

std::unordered_map<double, double> make_map(double times) {
    std::unordered_map<double, double> m(times);

    for (double c = 0; c < times; ++c) {
        m[c] = c + 10.0;
    }
    return m;
}

int main() {
    std::chrono::high_resolution_clock::time_point start_time = std::chrono::high_resolution_clock::now();
    auto m = make_map(10000000);
    std::chrono::high_resolution_clock::time_point end_time = std::chrono::high_resolution_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time-start_time);
    std::cout << elapsed.count()/1000000000. << "s\n";
    std::cout << m[10] << "\n"
              << m[9999999] << "\n";    
}

% g++ -dndebug -std=c++17 -ofast -o perf perf.cpp
% ./perf
2.81886s
20
1e+07

稍微修改了go版本:

package main

import (
    "fmt"
    "time"
)

func make_map(elem float64) map[float64]float64 {
    m := make(map[float64]float64, int(elem))
    var i float64 = 0
    for ; i < elem; i++ {
        m[i] = i + 10
    }
    return m
}

func main() {
    start_time := time.now()
    r := make_map(10000000)
    end_time := time.now()
    fmt.println(end_time.sub(start_time))
    fmt.println(r[10])
    fmt.println(r[9999999])
}

% go build -a perf.go
% ./perf
1.967707381s
20
1.0000009e+07

它看起来不像更新之前那样是平局。拖慢 cpp 版本速度的一件事是 double 的默认哈希函数。当用一个非常糟糕(但很快)的哈希器替换它时,我的时间减少到了 1.89489 秒。

struct bad_hasher {
    size_t operator()(const double& d) const {
        static_assert(sizeof(double)==sizeof(size_t));

        return
            *reinterpret_cast<const size_t*>( reinterpret_cast<const std::byte*>(&d) );
    }
};

确定“c++ 的速度”(几乎对于任何特定事物)有点困难,因为它可能取决于很多变量,例如您使用的编译器。例如,对于此代码的 c++ 版本,我通常会发现 gcc 和 msvc 之间存在 2:1 左右的差异。

就 c++ 和 go 之间的差异而言,我猜这主要是由于哈希表实现方式的差异。一个明显的一点是,go 的 map 实现一次以 8 个元素为一个块来分配数据空间。至少在我见过的标准库实现中,std::unordered_map 每个块仅放置一项。

我们预计这意味着在典型情况下,c++ 代码将从堆/空闲存储中执行更多数量的单独分配,因此其速度将在很大程度上取决于堆管理器的速度。 go 版本还应该具有更高的引用局部性,以便更好地利用缓存。

考虑到这些差异,我对您只看到 10:1 的差异感到有点惊讶。我的直接猜测会(稍微)高于这个数字,但众所周知,一次测量值胜过 100 次猜测。

参考

Go's Map Implementation

liststdc++ unordered_map

libc++ unordered_map

理论要掌握,实操不能落!以上关于《go和c++的map性能对比》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注编程网公众号吧!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

go和c++的map性能对比

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

go和c++的map性能对比

Golang小白一枚,正在不断学习积累知识,现将学习到的知识记录一下,也是将我的所得分享给大家!而今天这篇文章《go和c++的map性能对比》带大家来了解一下##content_title##,希望对大家的知识积累有所帮助,从而弥补自己的不
go和c++的map性能对比
2024-04-04

性能对比:Go语言与C语言的速度和效率

性能对比:Go语言与C语言的速度和效率在计算机编程领域,性能一直是开发者们关注的重要指标。在选择编程语言时,开发者通常会关注其速度和效率。Go语言和C语言作为两种流行的编程语言,被广泛用于系统级编程和高性能应用。本文将对比Go语言和C语言
性能对比:Go语言与C语言的速度和效率
2024-03-10

Go语言和Java的区别:性能对比

性能对比:Go语言和Java概述Go语言和Java都是流行的编程语言,但它们在性能方面存在一些差异。Go语言因其出色的并发性和低延迟而闻名,而Java则因其稳定性和跨平台性而受到欢迎。在本文中,我们将比较这两种语言在性能方面的优缺点,并
Go语言和Java的区别:性能对比
2024-02-01

Go库bytes.Buffer和strings.Builder使用及性能对比

这篇文章主要为大家介绍了Go库bytes.Buffer和strings.Builder使用及性能对比,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-15

Hadoop和spark的性能对比

本篇内容主要讲解“Hadoop和spark的性能对比”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Hadoop和spark的性能对比”吧!Hadoop和spark的性能有何区别。  如果说Had
2023-06-02

C++ vs Rust vs Go 性能比较

本文对C++、Rust和Go三种编程语言编写的gunzip程序进行了性能比较,通过基准测试试图尽可能公平的比较它们的性能。

Node、PHP、Java和Go服务端I/O性能对比

本篇内容主要讲解“Node、PHP、Java和Go服务端I/O性能对比”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Node、PHP、Java和Go服务端I/O性能对比”吧!了解应用程序的输入/
2023-06-20

c++矩阵计算性能对比:Eigen和GPU解读

这篇文章主要介绍了c++矩阵计算性能对比:Eigen和GPU解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-12-15

Go语言 vs Java:性能、并发和生态系统的对比

go和java在性能、并发和生态系统上存在差异。go以goroutine实现高效并发,在吞吐量密集型应用程序中优于java。java拥有庞大的生态系统,而go的生态系统正在快速发展。实战案例显示了go和java在不同领域的适用性,最终选择取
Go语言 vs Java:性能、并发和生态系统的对比
2024-04-08

PHP5和PHP8的性能和安全性:对比和改进

PHP是一种广泛应用的服务器端脚本语言,用于开发Web应用程序。它已经发展了多个版本,而本文将主要讨论PHP5和PHP8之间的比较,特别关注其在性能和安全性方面的改进。首先让我们来看看PHP5的一些特点。PHP5是在2004年发布的,它引
PHP5和PHP8的性能和安全性:对比和改进
2024-01-26

java中Memcached和Redis的性能对比

这篇文章将为大家详细讲解有关java中Memcached和Redis的性能对比,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面
2023-06-14

Laravel 和 CodeIgniter 的性能对比如何?

laravel 和 codeigniter 框架在性能上非常接近,差异很小,可能因应用程序用例而异。基准测试表明,codeigniter 在数据库查询方面略优,而 laravel 在某些视图渲染操作和路由解析方面略优。实战案例中,两者加载博
Laravel 和 CodeIgniter 的性能对比如何?
2024-05-12

C#和Java的对比

这篇文章主要介绍“C#和Java的对比”,在日常操作中,相信很多人在C#和Java的对比问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#和Java的对比”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!C#
2023-06-18

C++ 生态系统中流行库和框架的性能对比

c++++ 生态系统中,库和框架的性能表现各异:boost 在向量和字符串处理中卓著。eigen 在矩阵操作中效率最高。fmt 提供最快的字符串格式化。protobuf 在二进制序列化中拔得头筹。C++ 生态系统中流行库和框架的性能对比引
C++ 生态系统中流行库和框架的性能对比
2024-05-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录