ASM-function-call的开销

时间:2015-04-11 19:57:25

标签: performance optimization assembly go

我目前正在玩go,它的汇编,浮点运算(float32)的表现以及纳秒级的优化。我对一个简单函数调用的开销感到有点困惑:

func BenchmarkEmpty(b *testing.B) {
    for i := 0; i < b.N; i++ {
    }
}
func BenchmarkNop(b *testing.B) {
    for i := 0; i < b.N; i++ {
        doNop()
    }
}

doNop的实现:

TEXT ·doNop(SB),0,$0-0
    RET

结果(go test -bench .):

BenchmarkEmpty        2000000000               0.30 ns/op
BenchmarkNop  2000000000               1.73 ns/op

我不习惯组装和/或go的内部。 go编译器/链接器可以内联在程序集中定义的函数吗?我能以某种方式给链接器一个提示吗?对于一些简单的函数,例如&#39;添加两个R3-向量&#39;这会降低所有可能的性能提升。

(去1.4.2,amd64)

1 个答案:

答案 0 :(得分:0)

汇编函数未内联。以下是您可以尝试的三件事:

  1. 将循环移动到装配体中。例如,使用此功能:

    func Sum(xs []int64) int64
    

    你可以这样做:

    #include "textflag.h"
    
    TEXT ·Sum(SB),NOSPLIT,$0-24
        MOVQ  xs+0(FP),DI
        MOVQ  xs+8(FP),SI
        MOVQ  $0,CX
        MOVQ  $0,AX
    
    L1: CMPQ  AX,SI           // i < len(xs)
        JGE   Z1
        LEAQ  (DI)(AX*8),BX   // BX = &xs[i]
        MOVQ  (BX),BX         // BX = *BX
        ADDQ  BX,CX           // CX += BX
        INCQ  AX              // i++
        JMP   L1
    
    Z1: MOVQ  CX,ret+24(FP)
        RET
    

    如果您查看标准库,您将看到此示例。

  2. 在c中编写一些代码,利用它对内在函数或内联汇编的支持,并使用cgo从go调用它。

  3. 使用gccgo执行与#2相同的操作,但您可以直接执行此操作:

    //extern open
    func c_open(name *byte, mode int, perm int) int
    

    https://golang.org/doc/install/gccgo#Function_names