当前位置: 首页 > 面试题库 >

为什么cgo的性能这么慢?我的测试代码有问题吗?

晁聪
2023-03-14
问题内容

我正在做一个测试:比较cgo和纯Go函数的执行时间,每个函数运行一亿次。与Golang函数相比,cgo函数需要更长的时间,我对此结果感到困惑。我的测试代码是:

package main

import (
    "fmt"
    "time"
)

/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void show() {

}

*/
// #cgo LDFLAGS: -lstdc++
import "C"

//import "fmt"

func show() {

}

func main() {
    now := time.Now()
    for i := 0; i < 100000000; i = i + 1 {
        C.show()
    }
    end_time := time.Now()

    var dur_time time.Duration = end_time.Sub(now)
    var elapsed_min float64 = dur_time.Minutes()
    var elapsed_sec float64 = dur_time.Seconds()
    var elapsed_nano int64 = dur_time.Nanoseconds()
    fmt.Printf("cgo show function elasped %f minutes or \nelapsed %f seconds or \nelapsed %d nanoseconds\n",
        elapsed_min, elapsed_sec, elapsed_nano)

    now = time.Now()
    for i := 0; i < 100000000; i = i + 1 {
        show()
    }
    end_time = time.Now()

    dur_time = end_time.Sub(now)
    elapsed_min = dur_time.Minutes()
    elapsed_sec = dur_time.Seconds()
    elapsed_nano = dur_time.Nanoseconds()
    fmt.Printf("go show function elasped %f minutes or \nelapsed %f seconds or \nelapsed %d nanoseconds\n",
        elapsed_min, elapsed_sec, elapsed_nano)

    var input string
    fmt.Scanln(&input)
}

结果是:

cgo show function elasped 0.368096 minutes or 
elapsed 22.085756 seconds or 
elapsed 22085755775 nanoseconds

go show function elasped 0.000654 minutes or 
elapsed 0.039257 seconds or 
elapsed 39257120 nanoseconds

结果表明,调用C函数比Go函数要慢。我的测试代码有问题吗?

我的系统是:mac OS X 10.9.4(13E28)


问题答案:

正如您所发现的那样,通过CGo调用C / C
++代码的开销相当大。因此,一般而言,最好是尽量减少拨打CGo的次数。对于上面的示例,与其在循环中重复调用CGo函数,不如将循环向下移动到C。

Go运行时如何设置其线程可能会破坏许多C代码的期望,有很多方面:

  1. Goroutine在相对较小的堆栈上运行,通过分段堆栈(旧版本)或复制(新版本)来处理堆栈增长。
  2. Go运行时创建的线程可能无法与libpthread的线程本地存储实现正确交互。
  3. Go运行时的UNIX信号处理程序可能会干扰传统的C或C ++代码。
  4. Go重用OS线程来运行多个Goroutine。如果C代码调用了阻塞系统调用或以其他方式独占了线程,则可能对其他goroutine有害。

由于这些原因,CGo选择了在传统堆栈中设置的单独线程中运行C代码的安全方法。

如果您来自Python之类的语言,那么用C重写代码热点作为加速程序的一种方法并不少见,您会失望的。但是,与此同时,等效的C和Go代码之间的性能差距要小得多。

通常,我保留使用CGo与现有库进行接口,可能还使用小型C包装函数,这些函数可以减少我需要从Go进行的调用次数。



 类似资料:
  • 这个函数我传入一个数组提示arr.map不是函数?

  • 问题内容: 为什么在sqlite中:memory:这么慢? 我一直在尝试查看通过使用内存中的sqlite与基于磁盘的sqlite是否可以获得任何性能改进。基本上,我想以启动时间和内存为代价来获得非常快速的查询,这些查询在应用程序运行期间 不会 对磁盘造成影响。 但是,以下基准测试只能使我提高速度1.5倍。在这里,我正在生成一百万行随机数据,并将其加载到同一表的基于磁盘和内存的版本中。然后,我在两个

  • 我拿不到输出。。有人能帮我得到输出吗 下面给出了程序运行的示例(注意:下面的粗体文本是用户输入的输入): 输入三角形的三条边

  • 我在计算机课上遇到了合并排序的问题。我不断收到错误或返回原始ArrayList。 我相信合并排序涉及到将数组(列表)递归地对半拆分,直到只剩下一个元素,然后从这些单独的元素开始,按排序顺序合并它们。直到数组(列表)被排序为止。至于实际的排序部分,我试图在新的ArrayList中插入两半之间的较高值,直到它们都为空,在这种情况下,填充的ArrayList现在被排序。 这是我当前的代码: 我将感谢任何

  • **这是我的java代码,预期输出如下: 输入第一个数字:25 输入第二个数字:5 25 x 5=125 在我插入代码并运行它之后,输出与答案相差太大 以下是输出: 如何修复我的代码?