首页 > 解决方案 > Go 编译器会“压缩”函数吗?

问题描述

我对我工作的公司的一位工程师问我的一个问题很感兴趣,关于是否有一个遍历数组并测试两个条件的单个函数或者有两个函数,每个函数都有一个条件更好。

我来这里问你们我的理由是否错误。

代码是这样的:

response := ListObjectsFromS3(bucket)

var filteredEmptyObjectsArray = utils.FilterEmptyObjects(response)
var filteredNonJson = utils.FilterNonJson(filteredEmptyObjectsArray)

每个功能是:

func FilterEmptyObjects(arrayToFilter []*Object) []*Object {
    var filteredArray []*Object
    for _, object := range arrayToFilter {
        if *object.Size > 0 {
            filteredArray = append(filteredArray, object)
        }
    }

    return filteredArray
}

func FilterNonJson(arrayToFilter []*Object) []*Object {
    var filteredArray []*Object
    for _, object := range arrayToFilter {
        if strings.HasSuffix(*object.Key, ".json") {
            filteredArray = append(filteredArray, object)
        }
    }
    return filteredArray
}

请原谅上面代码中的重复。它是一个玩具示例。

我不确切知道 Go 是如何优化这段代码的,但我认为它可能会将这两个函数“压缩”成这样的东西——当然,不是在 Go 代码中,但生成的机器代码将等同于:

func FilterSquashed(arrayToFilter []*Object) []*Object {
    var filteredArray []*Object
    for _, object := range arrayToFilter {
        if strings.HasSuffix(*object.Key, ".json") && *object.Size > 0 {
            filteredArray = append(filteredArray, object)
        }
    }
    return filteredArray
}

响应的代码 - 也不是真正的 Go 代码,但编译器会生成一个机器码,相当于这样的东西:

response := utils.FilterSquashed(ListObjectsFromS3(bucket))

关键是,当我制作优化代码和非优化代码的 objdump 时,两者都将函数分开,并且CALL每个函数都有一个。因此,我试图了解当前可能的优化深度或 Go 编译器决定坚持的优化深度。

让我知道你的想法

标签: gocompilationcompiler-optimization

解决方案


您显示的“压缩”代码不等同于原始代码。代码优化的基本规则是优化和非优化代码的效果必须相同,但在您的示例中,您有两个函数应用不同的逻辑来过滤列表,第三个函数将应用第三种的逻辑,在这种特殊情况下会给你两个原始函数的组合,但不是在一般情况下。简而言之:在这种情况下,没有编译器会满足您的要求,因为语义不同。

在某些情况下内联某些函数时,编译器可能会发现更多优化,但我看不出您的示例如何从内联中受益。


推荐阅读