当一个变量超出循环、条件或案例的作用域后会发生什么?

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

What happens to a variable after it goes out of scope of a loop or a condition or a case?

问题

这个问题的原因只是出于我的好奇心,想确定在从多个通道读取大型字节数组的高性能流消费者编写方面,什么是最佳实践(尽管过早优化是万恶之源,但这只是出于好奇)。我已经阅读了关于类似情况的针对C的答案这里,但我请求针对Go的答案,因为它是一种垃圾回收的语言,他们的文档这里说:“从正确性的角度来看,你不需要知道变量在哪里分配”。

如果我有以下代码来从通道读取:

	for {
	select {
	case msg := <-stream.Messages():
    ...snip...

变量msgcase语句的作用域内。

  • 当它超出case语句的作用域时会发生什么?由于它在同一个本地函数中声明,并且stream的大小可能是一个大的字节切片,这个变量会被存储在堆还是栈中?如果是堆,它会被垃圾回收吗?或者栈指针会参与其中吗?

  • 由于这是在一个无限循环中,而stream的大小是一个大的字节切片,每次创建变量和分配内存是否会带来额外的开销?或者我应该提前声明变量,并在每次迭代中不断重写它,这样如果涉及垃圾回收(我不确定),我可能可以减少垃圾产生?

  • 我应该完全不用担心吗?

英文:

The reason for this question is just my curiosity to determine what could be the best practice on writing a high-performance stream consumer reading large size byte array from multiple channels. (although premature optimization is the root of all evil, this is more of a curiosity). I have read answers about similar senario specific to C here, but I am requesting answer specific to go, as it is a garbage collected language, and their documentation here says "From a correctness standpoint, you don't need to know where the variable is allocated".

If I have the following code to read from a channel,

	for {
	select {
	case msg := <-stream.Messages():
    ...snip...

Variable msg is within the scope of the case statement.

  • What happens once it goes out of scope of case statement? Since this is declared in the same native function, and the size of stream could be a large byte slice, is the variable going to be stored in heap or stack, and if heap, will it be garbage collected, or does stack pointer comes into picture?
  • Since this is inside an infinite for loop, and the size of stream is a large byte slice, is creating the variable and allocating memory every time an overhead,or should I declare the variable ahead, and keeps on over-writing it in every iteration, so that if there is a garbage collection involved, which I am not sure, I could possibly reduce the garbage?
  • Shouldn't I be bothered about it at all?

答案1

得分: 4

我不应该担心这个吗?

不需要。

(如果它让你烦恼:调整个人资料。)

英文:

> Shouldn't I be bothered about it at all?

No.

(And once it bothers you: profile.)

答案2

得分: 3

如果通道值类型是切片,则变量msg的值只是切片描述符,它很小(参见https://blog.golang.org/go-slices-usage-and-internals)。包含切片引用的数据的数组将在切片放入通道之前在其他地方分配。假设该值在分配它的函数返回后必须保留,它将位于堆上。请注意,切片的内容实际上并没有通过通道接收操作进行移动或复制。

一旦变量msg的值变得不可访问(通过变量超出作用域或被赋予不同的值),假设没有其他引用指向切片底层数组,它将被垃圾回收。

在不了解程序如何工作的情况下,很难确定是否有一定程度的优化会有所帮助。

英文:

If the channel value type is a slice, the value of the variable msg is just the slice descriptor, which is small (see https://blog.golang.org/go-slices-usage-and-internals). The array that contains the data the slice refers to will have been allocated elsewhere before the slice was placed on the channel. Assuming the value must survive after the function that allocated it returns, it will be on the heap. Note that the contents of the slice are not actually being moved or copied by the channel receive operation.

Once the value of msg becomes unreachable (by the variable going out of scope or being assigned a different value), assuming there are no other references to the array underlying the slice, it will be subject to garbage collection.

It's hard to say whether some amount of optimization would be helpful without knowing more about how the program works.

huangapple
  • 本文由 发表于 2017年3月6日 04:53:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/42613846.html
匿名

发表评论

匿名网友

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

确定