-
Notifications
You must be signed in to change notification settings - Fork 1.5k
refs: replace go_generics with Go generics #12470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
@nixprime could you take a loot at this pr too? |
|
@tamird Have we benchmarked the new ilist or refs implementation compared to their old go_generics one? IIRC, with Go generics, we add interface method calls and these types are on the hot paths for various subsystems. |
nixprime
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unlike go_generics, native Go generics only instantiate distinct code for different argument "shapes"; see https://github.com/golang/proposal/blob/master/design/generics-implementation-gcshape.md. AFAIU, all pointers have the same shape, so all instances of ilist.Entry[*T] and ilist.List[*T] use the same generated code, necessitating dynamic dispatch for ilist.Linker method calls after this change.
For example, before this change:
TEXT gvisor.dev/gvisor/pkg/sentry/kernel.(*pendingSignals).enqueue(SB) pkg/sentry/kernel/pending_signals.go
...
pending_signals_list.go:112 0xa9ec71 90 NOPL
pending_signals_list.go:231 0xa9ec72 48c70000000000 MOVQ $0x0, 0(AX)
pending_signals_list.go:113 0xa9ec79 488b4c2410 MOVQ 0x10(SP), CX
pending_signals_list.go:113 0xa9ec7e 488b542430 MOVQ 0x30(SP), DX
pending_signals_list.go:113 0xa9ec83 488b5cca08 MOVQ 0x8(DX)(CX*8), BX
pending_signals_list.go:238 0xa9ec88 833d312a7d0100 CMPL runtime.writeBarrier(SB), $0x0
pending_signals_list.go:238 0xa9ec8f 7408 JE 0xa9ec99
pending_signals_list.go:238 0xa9ec91 e80aa59eff CALL runtime.gcWriteBarrier1(SB)
pending_signals_list.go:238 0xa9ec96 49891b MOVQ BX, 0(R11)
pending_signals_list.go:238 0xa9ec99 48895808 MOVQ BX, 0x8(AX)
pending_signals_list.go:114 0xa9ec9d 488b5cca08 MOVQ 0x8(DX)(CX*8), BX
pending_signals_list.go:114 0xa9eca2 4885db TESTQ BX, BX
pending_signals_list.go:114 0xa9eca5 741d JE 0xa9ecc4
pending_signals_list.go:231 0xa9eca7 833d122a7d0100 CMPL runtime.writeBarrier(SB), $0x0
pending_signals_list.go:231 0xa9ecae 740f JE 0xa9ecbf
pending_signals_list.go:231 0xa9ecb0 488b33 MOVQ 0(BX), SI
pending_signals_list.go:231 0xa9ecb3 e808a59eff CALL runtime.gcWriteBarrier2(SB)
pending_signals_list.go:231 0xa9ecb8 498903 MOVQ AX, 0(R11)
pending_signals_list.go:231 0xa9ecbb 49897308 MOVQ SI, 0x8(R11)
pending_signals_list.go:231 0xa9ecbf 488903 MOVQ AX, 0(BX)
pending_signals_list.go:115 0xa9ecc2 eb1d JMP 0xa9ece1
pending_signals_list.go:117 0xa9ecc4 833df5297d0100 CMPL runtime.writeBarrier(SB), $0x0
pending_signals_list.go:117 0xa9eccb 7410 JE 0xa9ecdd
pending_signals_list.go:117 0xa9eccd 488b1cca MOVQ 0(DX)(CX*8), BX
pending_signals_list.go:117 0xa9ecd1 e8eaa49eff CALL runtime.gcWriteBarrier2(SB)
pending_signals_list.go:117 0xa9ecd6 498903 MOVQ AX, 0(R11)
pending_signals_list.go:117 0xa9ecd9 49895b08 MOVQ BX, 0x8(R11)
pending_signals_list.go:117 0xa9ecdd 488904ca MOVQ AX, 0(DX)(CX*8)
pending_signals_list.go:120 0xa9ece1 833dd8297d0100 CMPL runtime.writeBarrier(SB), $0x0
pending_signals_list.go:120 0xa9ece8 7411 JE 0xa9ecfb
pending_signals_list.go:120 0xa9ecea 488b5cca08 MOVQ 0x8(DX)(CX*8), BX
pending_signals_list.go:120 0xa9ecef e8cca49eff CALL runtime.gcWriteBarrier2(SB)
pending_signals_list.go:120 0xa9ecf4 498903 MOVQ AX, 0(R11)
pending_signals_list.go:120 0xa9ecf7 49895b08 MOVQ BX, 0x8(R11)
pending_signals_list.go:120 0xa9ecfb 488944ca08 MOVQ AX, 0x8(DX)(CX*8)
After this change:
TEXT gvisor.dev/gvisor/pkg/sentry/kernel.(*pendingSignals).enqueue(SB) pkg/sentry/kernel/pending_signals.go
...
pending_signals.go:101 0xa9c186 488d1d937fbd00 LEAQ gvisor.dev/gvisor/pkg/ilist..dict.List[*gvisor.dev/gvisor/pkg/sentry/kernel.pendingSignal](SB), BX
pending_signals.go:101 0xa9c18d e82e1d0500 CALL gvisor.dev/gvisor/pkg/ilist.(*List[go.shape.*gvisor.dev/gvisor/pkg/sentry/kernel.pendingSignal]).PushBack(SB)
...
TEXT gvisor.dev/gvisor/pkg/ilist.(*List[go.shape.*gvisor.dev/gvisor/pkg/sentry/kernel.pendingSignal]).PushBack(SB) pkg/ilist/list.go
list.go:124 0xaedec0 55 PUSHQ BP
list.go:124 0xaedec1 4889e5 MOVQ SP, BP
list.go:124 0xaedec4 4883ec18 SUBQ $0x18, SP
list.go:128 0xaedec8 4889442428 MOVQ AX, 0x28(SP)
list.go:128 0xaedecd 48895c2430 MOVQ BX, 0x30(SP)
list.go:128 0xaeded2 48894c2438 MOVQ CX, 0x38(SP)
list.go:126 0xaeded7 488d5308 LEAQ 0x8(BX), DX
list.go:126 0xaededb 4889542410 MOVQ DX, 0x10(SP)
list.go:126 0xaedee0 488b7308 MOVQ 0x8(BX), SI
list.go:126 0xaedee4 4889c8 MOVQ CX, AX
list.go:126 0xaedee7 31db XORL BX, BX
list.go:126 0xaedee9 ffd6 CALL SI
list.go:127 0xaedeeb 488b542430 MOVQ 0x30(SP), DX
list.go:127 0xaedef0 488d4a10 LEAQ 0x10(DX), CX
list.go:127 0xaedef4 488b7210 MOVQ 0x10(DX), SI
list.go:127 0xaedef8 488b7c2428 MOVQ 0x28(SP), DI
list.go:127 0xaedefd 488b5f08 MOVQ 0x8(DI), BX
list.go:127 0xaedf01 488b442438 MOVQ 0x38(SP), AX
list.go:127 0xaedf06 4889ca MOVQ CX, DX
list.go:127 0xaedf09 ffd6 CALL SI
list.go:128 0xaedf0b 488b4c2428 MOVQ 0x28(SP), CX
list.go:128 0xaedf10 488b4108 MOVQ 0x8(CX), AX
list.go:128 0xaedf14 4885c0 TESTQ AX, AX
list.go:128 0xaedf17 7529 JNE 0xaedf42
list.go:131 0xaedf19 833da037780100 CMPL runtime.writeBarrier(SB), $0x0
list.go:131 0xaedf20 7507 JNE 0xaedf29
list.go:131 0xaedf22 488b542438 MOVQ 0x38(SP), DX
list.go:131 0xaedf27 eb14 JMP 0xaedf3d
list.go:131 0xaedf29 488b01 MOVQ 0(CX), AX
list.go:131 0xaedf2c e88fb299ff CALL runtime.gcWriteBarrier2(SB)
list.go:131 0xaedf31 488b542438 MOVQ 0x38(SP), DX
list.go:131 0xaedf36 498913 MOVQ DX, 0(R11)
list.go:131 0xaedf39 49894308 MOVQ AX, 0x8(R11)
list.go:131 0xaedf3d 488911 MOVQ DX, 0(CX)
list.go:131 0xaedf40 eb1f JMP 0xaedf61
list.go:129 0xaedf42 488b4c2430 MOVQ 0x30(SP), CX
list.go:129 0xaedf47 488b4908 MOVQ 0x8(CX), CX
list.go:129 0xaedf4b 488b5c2438 MOVQ 0x38(SP), BX
list.go:129 0xaedf50 488b542410 MOVQ 0x10(SP), DX
list.go:129 0xaedf55 ffd1 CALL CX
list.go:134 0xaedf57 488b4c2428 MOVQ 0x28(SP), CX
list.go:134 0xaedf5c 488b542438 MOVQ 0x38(SP), DX
list.go:134 0xaedf61 833d5837780100 CMPL runtime.writeBarrier(SB), $0x0
list.go:134 0xaedf68 7410 JE 0xaedf7a
list.go:134 0xaedf6a 488b4108 MOVQ 0x8(CX), AX
list.go:134 0xaedf6e e84db299ff CALL runtime.gcWriteBarrier2(SB)
list.go:134 0xaedf73 498913 MOVQ DX, 0(R11)
list.go:134 0xaedf76 49894308 MOVQ AX, 0x8(R11)
list.go:134 0xaedf7a 48895108 MOVQ DX, 0x8(CX)
list.go:135 0xaedf7e 4883c418 ADDQ $0x18, SP
list.go:135 0xaedf82 5d POPQ BP
list.go:135 0xaedf83 c3 RET
Consequently, I don't think we should merge this change.
|
Thanks very much for the analysis! That makes sense, at least for ilist. How about the second commit that touches refs? |
|
I think the refs case is fine, with some changes:
I think you can avoid this by making the logging policies distinct shapes instead, as in https://github.com/google/gvisor/blob/master/pkg/bpf/input_bytes.go.
|
|
Done. Required some more go_stateify surgery, please have a look! |
|
Is there any benefits of using Go generics? |
We implement limited generics support: generic types must be monorphized by wrapping them with a struct that embeds them and is annotated with the new annotation `// +stateify transparent` which will generate a SaverLoader implementation that delegates to the wrapped type. This sidesteps the problem of generating a unique StateTypeName implementation for the generic type itself while keeping most of the code generated.
There's a big ergonomics benefit. Using bazel in editors is not very well supported, so anyone working on gvisor without the benefit of internal tooling can't easily jump to definition on types generated by |
|
Could I please get a CI run on this? |
|
The loggingPolicy thing in refs didn't work, there's still a runtime test and branching: It looks like it doesn't work in |
|
Apparently this is golang/go#59591. I tried inlining |
There are many more to do, but these are the most often used.