main.function STEXT size=108 args=0x8 locals=0x20 funcid=0x0 align=0x0
0x0000 00000 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) TEXT main.function(SB), ABIInternal, $32-8
0x0000 00000 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) CMPQ SP, 16(R14)
0x0004 00004 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $0, $-2
0x0004 00004 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) JLS 90
0x0006 00006 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $0, $-1
0x0006 00006 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PUSHQ BP
0x0007 00007 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) MOVQ SP, BP
0x000a 00010 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) SUBQ $24, SP
0x000e 00014 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) FUNCDATA $0, gclocals·ISb46fRPFoZ9pIfykFK/kQ==(SB)
0x000e 00014 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) FUNCDATA $1, gclocals·jCgrU8XAg0ifiSJZPFgpKw==(SB)
0x000e 00014 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) FUNCDATA $5, main.function.arginfo1(SB)
0x000e 00014 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) FUNCDATA $6, main.function.argliveinfo(SB)
0x000e 00014 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $3, $1
0x000e 00014 (/home/ritwikranjan/workplace/ethtool/test/main.go:20) MOVQ AX, main.x+40(SP)
0x0013 00019 (/home/ritwikranjan/workplace/ethtool/test/main.go:20) PCDATA $3, $-1
0x0013 00019 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) LEAQ type:main.ethtoolGStrings(SB), AX
0x001a 00026 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) PCDATA $1, $0
0x001a 00026 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) CALL runtime.newobject(SB)
0x001f 00031 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) MOVQ AX, main.&a+16(SP)
0x0024 00036 (/home/ritwikranjan/workplace/ethtool/test/main.go:18) LEAQ type:main.ethtoolStats(SB), AX
0x002b 00043 (/home/ritwikranjan/workplace/ethtool/test/main.go:18) PCDATA $1, $1
0x002b 00043 (/home/ritwikranjan/workplace/ethtool/test/main.go:18) CALL runtime.newobject(SB)
0x0030 00048 (/home/ritwikranjan/workplace/ethtool/test/main.go:20) MOVQ main.&a+16(SP), CX
0x0035 00053 (/home/ritwikranjan/workplace/ethtool/test/main.go:20) CMPL (CX), $0
0x0038 00056 (/home/ritwikranjan/workplace/ethtool/test/main.go:20) JEQ 82
0x003a 00058 (/home/ritwikranjan/workplace/ethtool/test/main.go:23) CMPL (AX), $0
0x003d 00061 (/home/ritwikranjan/workplace/ethtool/test/main.go:23) JNE 71
0x003f 00063 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) XORL AX, AX
0x0041 00065 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) ADDQ $24, SP
0x0045 00069 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) POPQ BP
0x0046 00070 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) RET
0x0047 00071 (/home/ritwikranjan/workplace/ethtool/test/main.go:27) MOVQ main.x+40(SP), AX
0x004c 00076 (/home/ritwikranjan/workplace/ethtool/test/main.go:27) ADDQ $24, SP
0x0050 00080 (/home/ritwikranjan/workplace/ethtool/test/main.go:27) POPQ BP
0x0051 00081 (/home/ritwikranjan/workplace/ethtool/test/main.go:27) RET
0x0052 00082 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) XORL AX, AX
0x0054 00084 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) ADDQ $24, SP
0x0058 00088 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) POPQ BP
0x0059 00089 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) RET
0x005a 00090 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) NOP
0x005a 00090 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $1, $-1
0x005a 00090 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $0, $-2
0x005a 00090 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) MOVQ AX, 8(SP)
0x005f 00095 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) NOP
0x0060 00096 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) CALL runtime.morestack_noctxt(SB)
0x0065 00101 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $0, $-1
0x0065 00101 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) MOVQ 8(SP), AX
0x006a 00106 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) JMP 0
|
main.function STEXT size=86 args=0x8 locals=0x100018 funcid=0x0 align=0x0
0x0000 00000 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) TEXT main.function(SB), ABIInternal, $1048600-8
0x0000 00000 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) MOVQ SP, R12
0x0003 00003 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $0, $-2
0x0003 00003 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) SUBQ $1048472, R12
0x000a 00010 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) JCS 79
0x000c 00012 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) CMPQ R12, 16(R14)
0x0010 00016 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) JLS 79
0x0012 00018 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $0, $-1
0x0012 00018 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PUSHQ BP
0x0013 00019 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) MOVQ SP, BP
0x0016 00022 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) SUBQ $1048592, SP
0x001d 00029 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x001d 00029 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x001d 00029 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) FUNCDATA $5, main.function.arginfo1(SB)
0x001d 00029 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) FUNCDATA $6, main.function.argliveinfo(SB)
0x001d 00029 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $3, $1
0x001d 00029 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) MOVUPS X15, main.a+4(SP)
0x0023 00035 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) LEAQ main.a+16(SP), DI
0x0028 00040 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) MOVL $131072, CX
0x002d 00045 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) XORL AX, AX
0x002f 00047 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) REP
0x0030 00048 (/home/ritwikranjan/workplace/ethtool/test/main.go:17) STOSQ
0x0032 00050 (/home/ritwikranjan/workplace/ethtool/test/main.go:20) CMPL main.a+4(SP), $0
0x0037 00055 (/home/ritwikranjan/workplace/ethtool/test/main.go:20) JNE 68
0x0039 00057 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) XORL AX, AX
0x003b 00059 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) ADDQ $1048592, SP
0x0042 00066 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) POPQ BP
0x0043 00067 (/home/ritwikranjan/workplace/ethtool/test/main.go:21) RET
0x0044 00068 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) XORL AX, AX
0x0046 00070 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) ADDQ $1048592, SP
0x004d 00077 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) POPQ BP
0x004e 00078 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) RET
0x004f 00079 (/home/ritwikranjan/workplace/ethtool/test/main.go:24) NOP
0x004f 00079 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $1, $-1
0x004f 00079 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $0, $-2
0x004f 00079 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) CALL runtime.morestack_noctxt(SB)
0x0054 00084 (/home/ritwikranjan/workplace/ethtool/test/main.go:16) PCDATA $0, $-1
|
Environment:
Problem Description:
When compiling the same code containing large struct variables within a function, Go 1.23 allocates these structs on the stack, while Go 1.24 allocates them on the heap (they escape).
Code Example:
Steps to Reproduce:
Save the code above as
main.go.Compile with Go 1.23 using escape analysis enabled:
go build -gcflags="-m" main.goOutput
Compile with Go 1.24 using escape analysis enabled:
go build -gcflags="-m" main.goOutput
Observed Behavior:
-gcflags="-m"does not indicate that variablesaandbescape to the heap. They appear to be stack-allocated as expected for local variables whose addresses don't escape.-gcflags="-m"does indicate that variablesaandbescape or are moved to the heap (e.g., showing lines like./main.go:17:2: moved to heap: aand./main.go:18:2: moved to heap: b).go build -gcflags="-S") for both versions confirms the difference in allocation strategy.Expected Behavior:
It was expected that the allocation behavior for these local structs would remain consistent between Go versions, primarily remaining on the stack, unless there's a documented change in escape analysis or stack size limits causing this. If this is an intentional change in Go 1.24 (perhaps related to stack size management or PGO), it would be helpful to have it documented.
Additional Context:
ethtoolGStringsandethtoolStatsare relatively large (approx 1MB and 256KB, respectively). Is there a new size threshold or heuristic in Go 1.24 causing large local variables to be heap-allocated by default?Thank you for looking into this.