【问题标题】:Does go compiler "squash" functions? [closed]Go 编译器会“压缩”函数吗? [关闭]
【发布时间】:2021-04-14 15:34:14
【问题描述】:

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

我来这里是想问你们我的理由是不是错了。

代码是这样的:

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 编译器决定坚持的优化深度。

让我知道你的想法

【问题讨论】:

  • 这不是编译器关心的那种优化;结果代码不再有效。这只是一次重构。
  • 嘿@Adrian,非常感谢您的评论。原始代码将遍历数组两次,而压缩后的代码只会遍历一次。我想知道你所说的“不再高效”是什么意思——你的意思是复杂性?
  • 有多个 Go 编译器。无论一个或任何一个执行您正在谈论的优化类型,都是一个实现细节,而不是规范的一部分,因此不是“Go”的一部分。如果您对特定编译器的特定版本执行的优化感到好奇,可以回答,但您需要指定。
  • 优化器执行您所描述的操作所需的逻辑跳跃次数远远超出了当今任何编译器所做的。也许有一天我们会有某种人工智能驱动的超级优化器,但与此同时,这种优化仍然是软件工程师的责任。

标签: go compilation compiler-optimization


【解决方案1】:

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

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

【讨论】:

  • 我在想编译器是否能够识别出可以执行这些压缩的这些受限情况。你怎么看?
  • 我不知道有任何编译器优化可以做到这一点。在这种受限情况下,唯一的优化是通过内联。编译器不太可能尝试识别两个单独的重要 for 循环是否相同,至少,我不知道有任何优化可以做到这一点。
猜你喜欢
  • 2011-07-17
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
相关资源
最近更新 更多