From: Josh Bleecher Snyder Date: Mon, 2 May 2016 01:02:41 +0000 (-0700) Subject: runtime: remove a load and shift from scanobject X-Git-Tag: go1.8beta1~1513 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=0e7e43688d2ad8b6c78bb865591eec96b6ce0e60;p=gostls13.git runtime: remove a load and shift from scanobject hbits.morePointers and hbits.isPointer both do a load and a shift. Do it only once. Benchmarks using compilebench (because it is the benchmark I have the most tooling around), on a quiet machine. name old time/op new time/op delta Template 291ms ±14% 290ms ±15% ~ (p=0.702 n=100+99) Unicode 143ms ± 9% 142ms ± 9% ~ (p=0.126 n=99+98) GoTypes 934ms ± 4% 933ms ± 4% ~ (p=0.937 n=100+100) Compiler 4.92s ± 2% 4.90s ± 1% -0.28% (p=0.003 n=98+98) name old user-ns/op new user-ns/op delta Template 360user-ms ± 5% 355user-ms ± 4% -1.37% (p=0.000 n=97+96) Unicode 178user-ms ± 6% 176user-ms ± 6% -1.24% (p=0.001 n=96+99) GoTypes 1.22user-s ± 5% 1.21user-s ± 5% -0.94% (p=0.000 n=100+100) Compiler 6.50user-s ± 2% 6.44user-s ± 3% -0.94% (p=0.000 n=96+98) On amd64, before: "".scanobject t=1 size=581 args=0x10 locals=0x78 After: "".scanobject t=1 size=540 args=0x10 locals=0x78 Change-Id: I420ac3704549d484a5d85e19fea82c85da389514 Reviewed-on: https://go-review.googlesource.com/22712 Run-TryBot: Josh Bleecher Snyder Reviewed-by: Austin Clements TryBot-Result: Gobot Gobot --- diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index aa7f7a7769..0c624d2cbc 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -1147,14 +1147,16 @@ func scanobject(b uintptr, gcw *gcWork) { // Avoid needless hbits.next() on last iteration. hbits = hbits.next() } + // Load bits once. See CL 22712 and issue 16973 for discussion. + bits := hbits.bits() // During checkmarking, 1-word objects store the checkmark // in the type bit for the one word. The only one-word objects // are pointers, or else they'd be merged with other non-pointer // data into larger allocations. - if i != 1*sys.PtrSize && !hbits.morePointers() { + if i != 1*sys.PtrSize && bits&bitScan == 0 { break // no more pointers in this object } - if !hbits.isPointer() { + if bits&bitPointer == 0 { continue // not a pointer }