Golangのcgo呼び出しのコスト

cgoでC言語の関数を呼び出す場合、普通の関数呼び出しの10倍くらいコストがかかりますね。ffiと同じくらいと見ればいいのかな? もっとかかってるのかも。

例えばこんな感じにしておいて、、、

package cgotest
import (
//#cgo LDFLAGS: -lm
//#include <math.h>
"C"
"math"
)
func CSin(x float64) float64 {
return float64(C.sin(C.double(x)))
}
func Sin(x float64) float64 {
return math.Sin(x)
}
view raw main.go hosted with ❤ by GitHub
package cgotest
import (
"math"
"testing"
)
func BenchmarkCSin(b *testing.B) {
for i := 0; i < b.N; i++ {
CSin(float64(i) / 1000.0)
}
}
func BenchmarkSin(b *testing.B) {
for i := 0; i < b.N; i++ {
Sin(float64(i) / 1000.0)
}
}
func BenchmarkMSin(b *testing.B) {
for i := 0; i < b.N; i++ {
math.Sin(float64(i) / 1000.0)
}
}

MBPで試してみると、こんな感じでした。

BenchmarkCSin-4 20000000 106 ns/op
BenchmarkSin-4 100000000 22.8 ns/op
BenchmarkMSin-4 100000000 20.0 ns/op

cgoを使って呼び出すことで5倍のコストがかかる。あとGolangの中で関数呼び出しが1段増えるだけだと3ns程度しか増えないのね。ライブラリ関数の呼び出しは内部関数の10倍、cgoはさらにその5倍…とかいう話なのかなこれは。

Golangはテストコードの中で直接cgoを使うことができない、という制約もあります。最初はxxx_test.goをいきなり作って、そこでcgoを使おうと思ったんですけど…直接cgoで書けないので、main.goを書く羽目になりました。

Golangで処理時間の短いC言語のライブラリを呼ぶのは得策ではなく、移植した方が良いだろうって話。

これ、お試しで xxHash(高速なハッシュ関数)のライブラリを呼び出してみようと https://github.com/wtnb75/go-xxhash を作りかけたんですが、試してみると標準ライブラリにあるCRCやAdlerに比べてあまりに遅いのでどうなんだろう…と思ったらcgoが遅かったと。そういう話です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です