【发布时间】: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