专栏首页高性能分布式系统设计如何把Go调用C的性能提升10倍?

如何把Go调用C的性能提升10倍?

目前,当Go需要和C/C++代码集成的时候,大家最先想到的肯定是CGO。毕竟是官方的解决方案,而且简单。

但是CGO是非常慢的。因为CGO其实一个桥接器,通过自动生成代码,CGO在保留了C/C++运行时的情况下,搭建了一个桥来沟通C/C++世界和Go的世界。这就意味着,兼容性很好,但是对C的函数的调用,必须先把当前的goroutine挂起,并切换执行栈到当前的线程M的主栈(大小2MB)。如果不做这个操作,那么只能在goroutine的栈上执行C函数调用,可是,goroutine的栈一般都很小,很容易就导致了栈溢出了。

调用C函数的时候,必须切换当前的栈为线程的主栈,这带来了两个比较严重的问题:

  1. 线程的栈在Go运行时是比较少的,受到P/M数量的限制,一般可以简单的理解成受到GOMAXPROCS限制;
  2. 由于需要同时保留C/C++的运行时,CGO需要在两个运行时和两个ABI(抽象二进制接口)之间做翻译和协调。这就带来了很大的开销。

minio项目的一个副产品是 c2goasm 项目,这个项目也被 go-cv-simd 项目使用获得了很好的效果。

c2goasm 的角色是一个 汇编语言转换器,输入是 clang输出的amd64汇编,输出是go汇编。而clang的输入是C/C++语言。限制是不能有RTTI和异常。也就是说不能有C/C++运行时提供的高级功能。

c2goasm输出的go汇编,交给go的工具链可以直接生成go的可执行代码。

c2goasm和CGO比,最大的改进就是:

  1. 不再有C/C++运行时,也就没了在两者之间不停转换的逻辑开销;
  2. 不需要切换到线程的主栈来执行函数,因为c2goasm生成的是纯正的go函数,不需要线程的主栈就可以执行;

由此就极大的改进了性能,代价是兼容性和可移植性损失了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 怎样判断iPhone/iPad是越狱的

    对开发者来说,越狱机盗版开发者的成果是一个灾难。 下面介绍一个方法来检测: 破解程序会在 Info.plist 加入 SignerIdentity 这个 KEY...

    Linker
  • Go的defer和方法修饰符的一个小坑

    先看代码: ? ? https://play.golang.org/p/GlM23bSW6zf 可见: 1. for 循环变量只有一份  2. 单行的defer...

    Linker
  • 写了一个Java like的ExecutorService的Go语言实现

    练习下刚刚学的Go语言。GoExecutors 主要用法可以看main.go文件。 主要是想用Java处理并发的ExecutorService系列工具类的模式,...

    Linker
  • 【小家java】Java中的线程池,你真的用对了吗?(教你用正确的姿势使用线程池,Executors使用中的坑)

    在【小家java】用 ThreadPoolExecutor/ThreadPoolTaskExecutor 线程池技术提高系统吞吐量(附带线程池参数详解和使用注意...

    YourBatman
  • 编程小知识之 Dispose 模式

    之前对 C# 中的 Dispose 模式只有些模糊印象,近来又了解了一些相关知识,在此简单做些记录~

    用户2615200
  • 最小子数组

    一份执着✘
  • mysql数据库查询表中相邻数据的差值

    二十三年蝉
  • 44. 最小子数组

    给定一个整数数组,找到一个具有最小和的子数组。返回其最小和。 样例 给出数组[1, -1, -2, 1],返回 -3 思路和最大子数组的思路基本是一样的,...

    和蔼的zhxing
  • Monte Carlo Tree Search (MCTS) 蒙特·卡罗尔树搜索

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    Steve Wang
  • 《2020 Offer收割机》| 线程安全法则

    我们的座右铭:“要好好学习,不然别人只会指着你的鼻子说“你看那个人,除了帅,一无是处。”

    王炸

扫码关注云+社区

领取腾讯云代金券