Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go Stack: Should it be Moving Like That?

Go Stack: Should it be Moving Like That?

Yarden Laifenfeld

June 28, 2023
Tweet

More Decks by Yarden Laifenfeld

Other Decks in Programming

Transcript

  1. 2 Who Am I? • Software Engineer at Rookout •

    Go, Java, Ruby • C#, Python, JavaScript, C++ • Amateur sewist
  2. What is Stack? • Section of memory ◦ One stack

    per thread • Works like a stack (LIFO) • Stores function parameters, local variables, return addresses 3
  3. What is Stack? 4 … func runFirst() { a :=

    1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... } Stack
  4. What is Stack? 5 … 1 a Local variables Stack

    func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... }
  5. What is Stack? 6 … 1 a Local variables Stack

    1 b Function parameters 2 c func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... }
  6. What is Stack? 7 … 1 a Local variables Stack

    1 b Function parameters 2 c 0x12345 Return address func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... }
  7. What is Stack? 8 … 1 a Local variables Stack

    1 b Function parameters 2 c 0x12345 Return address func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... } 0 d Local variables
  8. What is Stack? 9 … 1 a Local variables Stack

    1 b Function parameters 2 c 0x12345 Return address 0 d Local variables func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... }
  9. What is Stack? 10 … 1 a Local variables Stack

    1 b Function parameters 2 c 0x12345 Return address func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... }
  10. What is Stack? • Grows down - last thing we

    pushed onto the stack will be at the lowest address • RSP - “variable” that holds the last address of the stack 11
  11. What is Stack? 12 … 1 0x1238 Local variables Stack

    1 0x1230 Function parameters 2 0x1228 0x12345 func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... } Return address 0x1220
  12. What is Stack? 13 … 1 0x1238 Local variables Stack

    1 0x1230 Function parameters 2 0x1228 0x12345 func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... } Return address 0x1220 rsp
  13. What is Stack? 14 … 1 0x1238 Local variables Stack

    1 0x1230 Function parameters 2 0x1228 rsp Bigger rsp → smaller stack
  14. What’s So Special About Go? 15 • Threads ≠ Goroutines

    • Threads - 1-10MB • Goroutines - 4K
  15. When Is morestack Called? 17 • The compiler adds a

    prologue and epilogue to every function • Prologue checks if more stack is needed • Epilogue calls `morestack`
  16. needsMorestack() 19 • Not a real function • A condition

    that compares: ◦ Available stack ◦ Stack in use • How does that look like?
  17. g struct 21 Stack 0x1000 0x1008 0x1090 0x1088 0x1080 0x1010

    ... x x x rsp: 0x1078 g.stack.lo g.stack.hi
  18. g struct 22 Stack 0x1000 0x1008 0x1090 0x1088 0x1080 0x1010

    ... x x x x x x x x x x x x x x x rsp: 0x1010 x g.stack.lo g.stack.hi
  19. g struct 23 Stack 0x1000 0x1008 0x1090 0x1088 0x1080 0x1010

    ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x
  20. g struct 24 Stack 0x1000 0x1008 0x1090 0x1088 0x1080 0x1010

    ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x
  21. `morestack` needs 0x10 stack 26 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  22. `morestack` needs 0x10 stack 27 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  23. `morestack` needs 0x10 stack 28 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  24. `morestack` needs 0x10 stack 29 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  25. `morestack` needs 0x10 stack 30 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  26. `morestack` needs 0x10 stack 31 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  27. `morestack` needs 0x10 stack 32 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  28. `morestack` needs 0x10 stack 33 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  29. `morestack` needs 0x10 stack 34 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  30. `morestack` needs 0x10 stack 35 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  31. `morestack` needs 0x10 stack 36 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0x1000 x g.stack.lo g.stack.hi x x 0xff8 0xff0
  32. `morestack` needs 0x10 stack 37 Stack 0x1000 0x1008 0x1090 0x1088

    0x1080 0x1010 ... x x x x x x x x x x x x x x x rsp: 0xff0 x g.stack.lo g.stack.hi x x x x 0xff8 0xff0
  33. `morestack` needs 0x10 stack 38 38 Stack g.stack.lo g.stack.hi 0x1000

    0x1008 0x1090 0x1088 0x1080 0x1010 ... rsp: 0x1090 g.stack.lo+0x10
  34. `morestack` needs 0x10 stack 39 Stack g.stack.lo g.stack.hi 0x1000 0x1008

    0x1088 0x1080 0x1010 ... rsp: 0x1010 x x x x x x x x x x x x x x x x g.stack.lo+0x10
  35. `morestack` needs 0x10 stack 40 Stack g.stack.lo g.stack.hi 0x1000 0x1008

    0x1088 0x1080 0x1010 ... rsp: 0x1010 x x x x x x x x x x x x x x x x g.stack.lo+0x10
  36. `morestack` needs 0x10 stack 41 Stack g.stack.lo g.stack.hi 0x1000 0x1008

    0x1088 0x1080 0x1010 ... rsp: 0x1010 x x x x x x x x x x x x x x x x g.stack.lo+0x10
  37. `morestack` needs 0x10 stack 42 Stack g.stack.lo g.stack.hi 0x1000 0x1008

    0x1088 0x1080 0x1010 ... rsp: 0x1000 x x x x x x x x x x x x x x x x g.stack.lo+0x10 x x
  38. Stackguard 44 • Used to check if we have enough

    stack • Always between stack.lo and stack.hi • Will leave enough memory for calls to functions like `morestack`
  39. 45

  40. Stack Usage 48 Stack g.stack.lo g.stack.hi 0x1000 0x1008 0x1088 0x1080

    0x1010 ... rsp: 0x1020 x x x x x x x x x x x x x x g.stackguard0
  41. Stack Usage 49 Stack g.stack.lo g.stack.hi 0x1000 0x1008 0x1088 0x1080

    0x1010 ... rsp: 0x1020 x x x x x x x x x x x x x x g.stackguard0
  42. Stack Usage 50 Stack g.stack.lo g.stack.hi 0x1000 0x1008 0x1088 0x1080

    0x1010 ... rsp: 0x1020 x x x x x x x x x x x x x x g.stackguard0
  43. Stack Usage 51 Stack g.stack.lo g.stack.hi 0x1000 0x1008 0x1088 0x1080

    0x1010 ... rsp: 0xf20 x x x x x x x x x x x x x x g.stackguard0 x x x x x x x x x x x x x x x x
  44. What is Stack? 52 … func runFirst() { a :=

    1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... } Stack
  45. What is Stack? 53 … 1 a Local variables Stack

    func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... }
  46. What is Stack? 54 … 1 a Local variables Stack

    1 b Function parameters 2 c func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... }
  47. What is Stack? 55 … 1 a Local variables Stack

    1 b Function parameters 2 c func runFirst() { a := 1 runSecond(a, 2) return } func runSecond(b, c int) { var d int ... }
  48. What is Stack? 56 … 1 a Local variables Stack

    1 b Function parameters 2 c func runFirst() { a := 1 if shouldRunSecond { runSecond(a, 2) } return }
  49. Stack Usage 57 Stack g.stack.lo g.stack.hi 0x1000 0x1008 0x1088 0x1080

    0x1010 ... rsp: 0x1020 x x x x x x x x x x x x x x g.stackguard0
  50. Stack Usage 58 Stack g.stack.lo g.stack.hi 0x1000 0x1008 0x1088 0x1080

    0x1010 ... rsp: 0x1020 x x x x x x x x x x x x x x g.stackguard0
  51. Stack Usage 59 Stack g.stack.lo g.stack.hi 0x1000 0x1008 0x1088 0x1080

    0x1010 ... rsp: 0x1020 x x x x x x x x x x x x x x g.stackguard0
  52. Stack Shrink • `shrinkstack` • Called by GC • Shrink

    stack if less than a quarter is being used 62