作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的客户很简单。还有两个 goroutine:
package main
import (
"runtime"
)
func main() {
runtime.GOMAXPROCS(1)
go func() {
panic(1)
}()
for {
Test()
}
}
func Test() {
_ = make([]byte, 200)
a := 1
for {
a++
if a == 10 {
break
}
}
}
GODEBUG=asyncpreemptoff=1 go run main.go
最佳答案
好吧,我必须先说这个问题确实不适合 SO,因为它暗示了某种讨论——这已经在问题的原始版本的评论中发生了——最好在 the mailing list 上提出反而。
但是好的,让我们尝试解决您的问题的 v2,其中包含以下代码:
package main
import (
"runtime"
)
func main() {
runtime.GOMAXPROCS(1)
go func() {
panic(1)
}()
for {
Test()
}
}
func Test() {
_ = make([]byte, 200)
a := 1
for {
a++
if a == 10 {
break
}
}
}
go build -gcflags=-S preempt.go 2>preempt.S
stderr
,这就是为什么
2>...
),在
linux/amd64
和 Go 1.14.3 上,我们将得到(省略):
# command-line-arguments
"".main STEXT size=80 args=0x0 locals=0x18
0x0000 00000 (preempt.go:7) TEXT "".main(SB), ABIInternal, $24-0
0x0000 00000 (preempt.go:7) MOVQ (TLS), CX
0x0009 00009 (preempt.go:7) CMPQ SP, 16(CX)
0x000d 00013 (preempt.go:7) JLS 73
0x000f 00015 (preempt.go:7) SUBQ $24, SP
0x0013 00019 (preempt.go:7) MOVQ BP, 16(SP)
0x0018 00024 (preempt.go:7) LEAQ 16(SP), BP
0x001d 00029 (preempt.go:7) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (preempt.go:7) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x001d 00029 (preempt.go:7) FUNCDATA $2, gclocals·9fb7f0986f647f17cb53dda1484e0f7a(SB)
0x001d 00029 (preempt.go:8) PCDATA $0, $0
0x001d 00029 (preempt.go:8) PCDATA $1, $0
0x001d 00029 (preempt.go:8) MOVQ $1, (SP)
0x0025 00037 (preempt.go:8) CALL runtime.GOMAXPROCS(SB)
0x002a 00042 (preempt.go:9) MOVL $0, (SP)
0x0031 00049 (preempt.go:9) PCDATA $0, $1
0x0031 00049 (preempt.go:9) LEAQ "".main.func1·f(SB), AX
0x0038 00056 (preempt.go:9) PCDATA $0, $0
0x0038 00056 (preempt.go:9) MOVQ AX, 8(SP)
0x003d 00061 (preempt.go:9) CALL runtime.newproc(SB)
0x0042 00066 (preempt.go:13) CALL "".Test(SB)
0x0047 00071 (preempt.go:13) JMP 66
0x0049 00073 (preempt.go:13) NOP
0x0049 00073 (preempt.go:7) PCDATA $1, $-1
0x0049 00073 (preempt.go:7) PCDATA $0, $-1
0x0049 00073 (preempt.go:7) CALL runtime.morestack_noctxt(SB)
0x004e 00078 (preempt.go:7) JMP 0
<…>
"".Test STEXT nosplit size=17 args=0x0 locals=0x0
0x0000 00000 (preempt.go:17) TEXT "".Test(SB), NOSPLIT|ABIInternal, $0-0
0x0000 00000 (preempt.go:17) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0000 00000 (preempt.go:17) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0000 00000 (preempt.go:17) FUNCDATA $2, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0000 00000 (preempt.go:17) PCDATA $0, $0
0x0000 00000 (preempt.go:17) PCDATA $1, $0
0x0000 00000 (preempt.go:17) MOVL $1, AX
0x0005 00005 (preempt.go:20) JMP 10
0x0007 00007 (preempt.go:21) INCQ AX
0x000a 00010 (preempt.go:22) CMPQ AX, $9
0x000e 00014 (preempt.go:22) JNE 7
0x0010 00016 (<unknown line number>) PCDATA $0, $-2
0x0010 00016 (<unknown line number>) PCDATA $1, $-2
0x0010 00016 (<unknown line number>) RET
<…>
main
的主体开始,然后以
Test
的主体继续。
main
中,最感兴趣的是以下位:
0x0042 00066 (preempt.go:13) CALL "".Test(SB)
0x0047 00071 (preempt.go:13) JMP 66
for
循环变成了
CALL
到
Test
函数,然后是无条件
JMP
到
CALL
的地址。
Test
的代码。
0x0000 00000 (preempt.go:17) TEXT "".Test(SB), NOSPLIT|ABIInternal, $0-0
NOSPLIT
位。
For example, here is a simple complete function definition. The
TEXT
directive declares the symbol <…> and the instructions that follow form the body of the function.<…>
NOSPLIT = 4
(ForTEXT
items.) Don't insert the preamble to check if the stack must be split. The frame for the routine, plus anything it calls, must fit in the spare space at the top of the stack segment. Used to protect routines such as the stack splitting code itself.
Test
没有在其堆栈上分配任何东西,因此它永远不会使用超出其自己的堆栈帧(由调用者分配)之外的任何堆栈空间,因此编译器继续并标记该函数为
NOSPLIT
以消除任何运行时检查以增加堆栈的需要 - 以获得调用加速。
go tool objdump
来反汇编已构建的可执行镜像。
关于go - 为什么 goroutine 饿死了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61915917/
我是一名优秀的程序员,十分优秀!