Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么通过go插件调用函数比直接调用函数更快_Go_Plugins_Benchmarking - Fatal编程技术网

为什么通过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))

我想对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))
    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/op
BenchmarkPluginRandInt-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