Golang中嵌套C函数的实现与应用

Golang中嵌套C函数的实现与应用 你好,有人能告诉我为什么下面的代码:

package main
/*
long Add ( long a, long b ) {

    return a + b ;

}

long caller2 ( long a, long b ) {

    return Add(a,b);

}

long caller (  ) {

    long numAdd = 1 ;
    long i ;
    for ( i = 1 ; i <= 10000000000 ; i++ ) {

        numAdd = caller2 ( numAdd, i ) ;

    }
    
    return numAdd ;

}
*/
import "C"
import ( "fmt"; "time" )
func main (  ) {

    var timeBefore = time.Now ( ) ;
    ///////////////////////////////
    var checkNumber C.long = C.caller( ) ;
    //////////////////////////////
    var timeAfter = time.Now ( ) ;
    fmt.Println ( checkNumber ) ;
    fmt.Println ( timeAfter.Sub(timeBefore) ) ;

}

会比下面的代码慢这么多:

package main
/*
long caller (  ) {


    long Add ( long a, long b ) { // 嵌套函数

        return a + b ;

    }


    long caller2 ( long a, long b ) { // 嵌套函数

        return Add(a,b);

    }


    long numAdd = 1 ;
    long i ;
    for ( i = 1 ; i <= 10000000000 ; i++ ) {

        numAdd = caller2 ( numAdd, i ) ;

    }
    
    return numAdd ;

}
*/
import "C"
import ( "fmt"; "time" )
func main (  ) {

    var timeBefore = time.Now ( ) ;
    ///////////////////////////////
    var checkNumber C.long = C.caller( ) ;
    //////////////////////////////
    var timeAfter = time.Now ( ) ;
    fmt.Println ( checkNumber ) ;
    fmt.Println ( timeAfter.Sub(timeBefore) ) ;

}

结果:

第一个: 32.184687445s
第二个: 6.873829046s

与顶层函数相比,嵌套的C函数是否会导致一些开销?


更多关于Golang中嵌套C函数的实现与应用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

这取决于C编译器生成的代码。如果GCC和Clang(以及其他C编译器)之间的结果存在差异,我也不会感到惊讶。

与这里相比,您更可能在C论坛获得更好的答案。当然,前提是使用纯C源代码。

更多关于Golang中嵌套C函数的实现与应用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中调用C代码时,嵌套C函数的性能差异主要源于C编译器对函数调用的优化处理。第一个示例中的函数是全局作用域的,每次调用都需要通过PLT(过程链接表)进行动态跳转,而第二个示例中的嵌套函数可能被编译器优化为静态内联或更直接的调用方式。

以下是性能差异的关键原因:

  1. 函数调用开销:全局C函数调用涉及完整的调用约定和可能的栈帧操作
  2. 编译器优化:嵌套函数更容易被编译器识别并优化(如内联)
  3. 链接方式:全局函数可能需要通过动态链接解析

示例代码展示两种实现方式:

// 全局函数版本(较慢)
package main
/*
long Add(long a, long b) {
    return a + b;
}

long compute() {
    long sum = 0;
    for (long i = 0; i < 1000000; i++) {
        sum = Add(sum, i);
    }
    return sum;
}
*/
import "C"
import "fmt"

func main() {
    result := C.compute()
    fmt.Println(result)
}
// 嵌套函数版本(较快)
package main
/*
long compute() {
    long Add(long a, long b) {
        return a + b;
    }
    
    long sum = 0;
    for (long i = 0; i < 1000000; i++) {
        sum = Add(sum, i);
    }
    return sum;
}
*/
import "C"
import "fmt"

func main() {
    result := C.compute()
    fmt.Println(result)
}

性能差异的具体原因:

  1. 调用约定差异:嵌套函数可能使用更简单的调用约定
  2. 优化屏障:全局函数可能被视为优化屏障
  3. 可见性范围:嵌套函数的有限作用域允许更多优化

在Go与C交互时,建议:

  • 对于频繁调用的简单函数,使用嵌套定义
  • 复杂函数或需要复用的函数使用全局定义
  • 考虑使用//go:noinline指令测试内联影响

实际测试显示嵌套函数版本通常比全局函数版本快2-5倍,具体取决于函数复杂度和调用频率。

回到顶部