在go1.4中,是否有必要放弃太大的堆栈变量以避免堆栈复制?

huangapple go评论80阅读模式
英文:

Is it necessary to abandon too large variable on stack to avoid stack copying in go1.4?

问题

我们知道,在Go 1.4中,goroutine的堆栈可以通过复制堆栈来增加。我的问题是,在Go语言中,是否有必要避免在堆栈上使用过大的局部变量呢?

例如:

func foo(){
   var buf [8096]int
   //对buf进行操作
}

或者:

var buf [8096]int
func foo(){      
   //对buf进行操作
}

我的意思是,是否有必要使用后一种示例来避免由于堆栈复制而导致的大变量?

英文:

As we know, goroutine's stack could increase by copying the stack in go1.4. My question is, Is it necessary to avoid too large local variable on stack in go?
for example

func foo(){
   var buf [8096]int
   //do something with buf
}

or

var buf [8096]int
func foo(){      
   //do something with buf
}

I mean, is it necessary to use the latter example to avoid large variable because of stack copying?

答案1

得分: 2

栈(Stack)几乎总是比堆(Heap)更快。变量的定义位置更多地涉及作用域。由于Go是一种词法作用域语言,在后面的示例中,你会污染全局命名空间,使得变量buf在程序的任何地方都可见。这是语义上的区别。因此,你应该更好地按照语义正确的方式进行操作。

英文:

Stack is almost always faster then heap. Where to define variable is more about scope. Since Go is lexically scoped language in latter example you dirty up global namespace, making var buf visible anywhere in your program. It's semantic difference. So you should better do things semanticaly correct.

答案2

得分: 0

如果你不想在堆栈中重新分配另一个大对象,你应该使用指针而不是全局变量。至于go1.4,这段代码是有效的:

package main

import "fmt"

func do(v *[3]int) {
    v[1] = 99
}

func main() {
    var r [3]int
    do(&r)
    fmt.Println(r)
    //输出 [0 99 0]
}

如果你不使用指针,这段代码将失败,因为数组是按值传递而不是按引用传递的:

package main

import "fmt"

func do(v [3]int) {
    v[1] = 99
}

func main() {
    var r [3]int
    do(r)
    fmt.Println(r)
    //输出 [0 0 0]
}

注意:这不适用于切片;切片始终按引用传递。

英文:

If you don't want to reallocate another big object in the stack you should use pointer instead of global variables. As for go1.4 this code works:

package main

import "fmt"

func do(v *[3]int) {
    v[1] = 99
}

func main() {
    var r [3]int
    do(&r)
    fmt.Println(r)
    //Prints [0 99 0]
}

If you don't use pointers this will fail because arrays are passed as value, not reference:

package main

import "fmt"

func do(v [3]int) {
    v[1] = 99
}

func main() {
    var r [3]int
    do(r)
    fmt.Println(r)
    //Prints [0 0 0]
}

Note: this does not apply to slices; slices are always passed as reference.

huangapple
  • 本文由 发表于 2014年12月26日 10:30:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/27652294.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定