为什么通过go插件调用函数比直接调用函数更快
我想对go插件进行基准测试,看看性能差异是什么。因此,我用以下代码创建了一个main.go文件:为什么通过go插件调用函数比直接调用函数更快,go,plugins,benchmarking,Go,Plugins,Benchmarking,我想对go插件进行基准测试,看看性能差异是什么。因此,我用以下代码创建了一个main.go文件: package main import ( "math/rand" "strings" ) // RandString generates and returns a random 50 character string func RandString(n int) string { rand.Seed(int64(n))
package main
import (
"math/rand"
"strings"
)
// RandString generates and returns a random 50 character string
func RandString(n int) string {
rand.Seed(int64(n))
chars := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz" +
"0123456789")
var b strings.Builder
for i := 0; i < 50; i++ {
b.WriteRune(chars[rand.Intn(len(chars))])
}
return b.String()
}
接下来,我编写了两个基准函数来测试内联运行函数与通过go插件运行函数的性能
// BenchmarkRandString tests generating a random string without a go plugin
func BenchmarkRandString(b *testing.B) {
for i := 0; i < b.N; i++ {
RandString(rand.Int())
}
}
// BenchmarkPluginRandString tests generating a random string with a go plugin
func BenchmarkPluginRandString(b *testing.B) {
plug, err := plugin.Open("./plugin.so")
if err != nil {
panic(err)
}
randString, err := plug.Lookup("RandString")
if err != nil {
panic(err)
}
randFunc, ok := randString.(func(n int) string)
if !ok {
panic("unexpected type from module symbol")
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
randFunc(rand.Int())
}
}
然后,在前两个基准函数的基础上添加了新的基准函数
// BenchmarkRandInt tests math/rand for generating random integers without a go plugin
func BenchmarkRandInt(b *testing.B) {
for i := 0; i < b.N; i++ {
RandInt()
}
}
// BenchmarkPluginRandInt uses a go plugin and tests math/rand for generating random integers
func BenchmarkPluginRandInt(b *testing.B) {
plug, err := plugin.Open("./plugin.so")
if err != nil {
panic(err)
}
randInt, err := plug.Lookup("RandInt")
if err != nil {
panic(err)
}
randFunc, ok := randInt.(func() int)
if !ok {
panic("unexpected type from module symbol")
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
randFunc()
}
}
//BenchmarkRandInt测试数学/随机数,以便在没有go插件的情况下生成随机整数
func BenchmarkRandInt(b*testing.b){
对于i:=0;i
现在,当我再次运行基准测试时,我得到以下结果:
BenchmarkRandInt-12 77320668 13.2 ns/opBenchmarkPluginRandInt-12 76371756 13.9 ns/op
BenchmarkRandString-12 136243 8600 ns/op
基准插件随机串-12 142112 8564 ns/op 我可以一次又一次地运行基准测试,而BenchmarkRandString-12总是比BenchmarkPluginRandString-12慢一点,这不是我所期望的。为什么像这样进行基准测试时go插件的功能会稍微快一点 我有一个Github项目,其中包含了我在这里使用的所有源代码:使用“plugin”函数可能会慢一些的是它的加载和类型断言。完成后,与应用程序中定义的功能相比,应该不会有性能损失 如此小的偏差可能是Go内部内存管理和垃圾收集的结果。例如,如果在您的
main\u test.go
文件中,我将BenchmarkPluginRandString()
移动到BenchmarkRandString()
上方,那么基准测试结果将“反转”:BenchmarkRandString()
会稍微变慢
为了消除这些不确定因素,您可以尝试单独运行基准测试,例如,使用
go test -bench BenchmarkRandString
及
多次这样做,然后计算平均值。这样就没有明显的区别了
// BenchmarkRandInt tests math/rand for generating random integers without a go plugin
func BenchmarkRandInt(b *testing.B) {
for i := 0; i < b.N; i++ {
RandInt()
}
}
// BenchmarkPluginRandInt uses a go plugin and tests math/rand for generating random integers
func BenchmarkPluginRandInt(b *testing.B) {
plug, err := plugin.Open("./plugin.so")
if err != nil {
panic(err)
}
randInt, err := plug.Lookup("RandInt")
if err != nil {
panic(err)
}
randFunc, ok := randInt.(func() int)
if !ok {
panic("unexpected type from module symbol")
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
randFunc()
}
}
go test -bench BenchmarkRandString
go test -bench BenchmarkPluginRandString