1. 28 Apr, 2016 3 commits
  2. 27 Apr, 2016 28 commits
  3. 26 Apr, 2016 9 commits
    • Austin Clements's avatar
      runtime: make stack re-scan O(# dirty stacks) · 2a889b9d
      Austin Clements authored
      Currently the stack re-scan during mark termination is O(# stacks)
      because we enqueue a root marking job for every goroutine. It takes
      ~34ns to process this root marking job for a valid (clean) stack, so
      at around 300k goroutines we exceed the 10ms pause goal. A non-trivial
      portion of this time is spent simply taking the cache miss to check
      the gcscanvalid flag, so simply optimizing the path that handles clean
      stacks can only improve this so much.
      
      Fix this by keeping an explicit list of goroutines with dirty stacks
      that need to be rescanned. When a goroutine first transitions to
      running after a stack scan and marks its stack dirty, it adds itself
      to this list. We enqueue root marking jobs only for the goroutines in
      this list, so this improves stack re-scanning asymptotically by
      completely eliminating time spent on clean goroutines.
      
      This reduces mark termination time for 500k idle goroutines from 15ms
      to 238µs. Overall performance effect is negligible.
      
      name \ 95%ile-time/markTerm     old           new         delta
      IdleGs/gs:500000/gomaxprocs:12  15000µs ± 0%  238µs ± 5%  -98.41% (p=0.000 n=10+10)
      
      name              old time/op  new time/op  delta
      XBenchGarbage-12  2.30ms ± 3%  2.29ms ± 1%  -0.43%  (p=0.049 n=17+18)
      
      name                      old time/op    new time/op    delta
      BinaryTree17-12              2.57s ± 3%     2.59s ± 2%    ~     (p=0.141 n=19+20)
      Fannkuch11-12                2.09s ± 0%     2.10s ± 1%  +0.53%  (p=0.000 n=19+19)
      FmtFprintfEmpty-12          45.3ns ± 3%    45.2ns ± 2%    ~     (p=0.845 n=20+20)
      FmtFprintfString-12          129ns ± 0%     127ns ± 0%  -1.55%  (p=0.000 n=16+16)
      FmtFprintfInt-12             123ns ± 0%     119ns ± 1%  -3.24%  (p=0.000 n=19+19)
      FmtFprintfIntInt-12          195ns ± 1%     189ns ± 1%  -3.11%  (p=0.000 n=17+17)
      FmtFprintfPrefixedInt-12     193ns ± 1%     187ns ± 1%  -3.06%  (p=0.000 n=19+19)
      FmtFprintfFloat-12           254ns ± 0%     255ns ± 1%  +0.35%  (p=0.001 n=14+17)
      FmtManyArgs-12               781ns ± 0%     770ns ± 0%  -1.48%  (p=0.000 n=16+19)
      GobDecode-12                7.00ms ± 1%    6.98ms ± 1%    ~     (p=0.563 n=19+19)
      GobEncode-12                5.91ms ± 1%    5.92ms ± 0%    ~     (p=0.118 n=19+18)
      Gzip-12                      219ms ± 1%     215ms ± 1%  -1.81%  (p=0.000 n=18+18)
      Gunzip-12                   37.2ms ± 0%    37.4ms ± 0%  +0.45%  (p=0.000 n=17+19)
      HTTPClientServer-12         76.9µs ± 3%    77.5µs ± 2%  +0.81%  (p=0.030 n=20+19)
      JSONEncode-12               15.0ms ± 0%    14.8ms ± 1%  -0.88%  (p=0.001 n=15+19)
      JSONDecode-12               50.6ms ± 0%    53.2ms ± 2%  +5.07%  (p=0.000 n=17+19)
      Mandelbrot200-12            4.05ms ± 0%    4.05ms ± 1%    ~     (p=0.581 n=16+17)
      GoParse-12                  3.34ms ± 1%    3.30ms ± 1%  -1.21%  (p=0.000 n=15+20)
      RegexpMatchEasy0_32-12      69.6ns ± 1%    69.8ns ± 2%    ~     (p=0.566 n=19+19)
      RegexpMatchEasy0_1K-12       238ns ± 1%     236ns ± 0%  -0.91%  (p=0.000 n=17+13)
      RegexpMatchEasy1_32-12      69.8ns ± 1%    70.0ns ± 1%  +0.23%  (p=0.026 n=17+16)
      RegexpMatchEasy1_1K-12       371ns ± 1%     363ns ± 1%  -2.07%  (p=0.000 n=19+19)
      RegexpMatchMedium_32-12      107ns ± 2%     106ns ± 1%  -0.51%  (p=0.031 n=18+20)
      RegexpMatchMedium_1K-12     33.0µs ± 0%    32.9µs ± 0%  -0.30%  (p=0.004 n=16+16)
      RegexpMatchHard_32-12       1.70µs ± 0%    1.70µs ± 0%  +0.45%  (p=0.000 n=16+17)
      RegexpMatchHard_1K-12       51.1µs ± 2%    51.4µs ± 1%  +0.53%  (p=0.000 n=17+19)
      Revcomp-12                   378ms ± 1%     385ms ± 1%  +1.92%  (p=0.000 n=19+18)
      Template-12                 64.3ms ± 2%    65.0ms ± 2%  +1.09%  (p=0.001 n=19+19)
      TimeParse-12                 315ns ± 1%     317ns ± 2%    ~     (p=0.108 n=18+20)
      TimeFormat-12                360ns ± 1%     337ns ± 0%  -6.30%  (p=0.000 n=18+13)
      [Geo mean]                  51.8µs         51.6µs       -0.48%
      
      Change-Id: Icf8994671476840e3998236e15407a505d4c760c
      Reviewed-on: https://go-review.googlesource.com/20700Reviewed-by: default avatarRick Hudson <rlh@golang.org>
      Run-TryBot: Austin Clements <austin@google.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      2a889b9d
    • Austin Clements's avatar
      runtime: don't clear gcscanvalid in casfrom_Gscanstatus · 5b765ce3
      Austin Clements authored
      Currently we clear gcscanvalid in both casgstatus and
      casfrom_Gscanstatus if the new status is _Grunning. This is very
      important to do in casgstatus. However, this is potentially wrong in
      casfrom_Gscanstatus because in this case the caller doesn't own gp and
      hence the write is racy. Unlike the other _Gscan statuses, during
      _Gscanrunning, the G is still running. This does not indicate that
      it's transitioning into a running state. The scan simply hasn't
      happened yet, so it's neither valid nor invalid.
      
      Conveniently, this also means clearing gcscanvalid is unnecessary in
      this case because the G was already in _Grunning, so we can simply
      remove this code. What will happen instead is that the G will be
      preempted to scan itself, that scan will set gcscanvalid to true, and
      then the G will return to _Grunning via casgstatus, clearing
      gcscanvalid.
      
      This fix will become necessary shortly when we start keeping track of
      the set of G's with dirty stacks, since it will no longer be
      idempotent to simply set gcscanvalid to false.
      
      Change-Id: I688c82e6fbf00d5dbbbff49efa66acb99ee86785
      Reviewed-on: https://go-review.googlesource.com/20669Reviewed-by: default avatarRick Hudson <rlh@golang.org>
      Run-TryBot: Austin Clements <austin@google.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      5b765ce3
    • Austin Clements's avatar
      runtime: fix typos in comment about gcscanvalid · c707d838
      Austin Clements authored
      Change-Id: Id4ad7ebf88a21eba2bc5714b96570ed5cfaed757
      Reviewed-on: https://go-review.googlesource.com/22210Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
      Run-TryBot: Austin Clements <austin@google.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      c707d838
    • Austin Clements's avatar
      runtime: remove stack barriers during sweep · 9f263c14
      Austin Clements authored
      This adds a best-effort pass to remove stack barriers immediately
      after the end of mark termination. This isn't necessary for the Go
      runtime, but should help external tools that perform stack walks but
      aren't aware of Go's stack barriers such as GDB, perf, and VTune.
      (Though clearly they'll still have trouble unwinding stacks during
      mark.)
      
      Change-Id: I66600fae1f03ee36b5459d2b00dcc376269af18e
      Reviewed-on: https://go-review.googlesource.com/20668Reviewed-by: default avatarRick Hudson <rlh@golang.org>
      Run-TryBot: Austin Clements <austin@google.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      9f263c14
    • Austin Clements's avatar
      runtime: remove stack barriers during concurrent mark · 269c969c
      Austin Clements authored
      Currently we remove stack barriers during STW mark termination, which
      has a non-trivial per-goroutine cost and means that we have to touch
      even clean stacks during mark termination. However, there's no problem
      with leaving them in during the sweep phase. They just have to be out
      by the time we install new stack barriers immediately prior to
      scanning the stack such as during the mark phase of the next GC cycle
      or during mark termination in a STW GC.
      
      Hence, move the gcRemoveStackBarriers from STW mark termination to
      just before we install new stack barriers during concurrent mark. This
      removes the cost from STW. Furthermore, this combined with concurrent
      stack shrinking means that the mark termination scan of a clean stack
      is a complete no-op, which will make it possible to skip clean stacks
      entirely during mark termination.
      
      This has the downside that it will mess up anything outside of Go that
      tries to walk Go stacks all the time instead of just some of the time.
      This includes tools like GDB, perf, and VTune. We'll improve the
      situation shortly.
      
      Change-Id: Ia40baad8f8c16aeefac05425e00b0cf478137097
      Reviewed-on: https://go-review.googlesource.com/20667Reviewed-by: default avatarRick Hudson <rlh@golang.org>
      Run-TryBot: Austin Clements <austin@google.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      269c969c
    • Austin Clements's avatar
      runtime: avoid span root marking entirely during mark termination · efb0c554
      Austin Clements authored
      Currently we enqueue span root mark jobs during both concurrent mark
      and mark termination, but we make the job a no-op during mark
      termination.
      
      This is silly. Instead of queueing them up just to not do them, don't
      queue them up in the first place.
      
      Change-Id: Ie1d36de884abfb17dd0db6f0449a2b7c997affab
      Reviewed-on: https://go-review.googlesource.com/20666Reviewed-by: default avatarRick Hudson <rlh@golang.org>
      Run-TryBot: Austin Clements <austin@google.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      efb0c554
    • Austin Clements's avatar
      runtime: free dead G stacks concurrently · e8337491
      Austin Clements authored
      Currently we free cached stacks of dead Gs during STW stack root
      marking. We do this during STW because there's no way to take
      ownership of a particular dead G, so attempting to free a dead G's
      stack during concurrent stack root marking could race with reusing
      that G.
      
      However, we can do this concurrently if we take a completely different
      approach. One way to prevent reuse of a dead G is to remove it from
      the free G list. Hence, this adds a new fixed root marking task that
      simply removes all Gs from the list of dead Gs with cached stacks,
      frees their stacks, and then adds them to the list of dead Gs without
      cached stacks.
      
      This is also a necessary step toward rescanning only dirty stacks,
      since it eliminates another task from STW stack marking.
      
      Change-Id: Iefbad03078b284a2e7bf30fba397da4ca87fe095
      Reviewed-on: https://go-review.googlesource.com/20665Reviewed-by: default avatarRick Hudson <rlh@golang.org>
      Run-TryBot: Austin Clements <austin@google.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      e8337491
    • Austin Clements's avatar
      runtime: split gfree list into with-stacks and without-stacks · 1a2cf91f
      Austin Clements authored
      Currently all free Gs are added to one list. Split this into two
      lists: one for free Gs with cached stacks and one for Gs without
      cached stacks.
      
      This lets us preferentially allocate Gs that already have a stack, but
      more importantly, it sets us up to free cached G stacks concurrently.
      
      Change-Id: Idbe486f708997e1c9d166662995283f02d1eeb3c
      Reviewed-on: https://go-review.googlesource.com/20664Reviewed-by: default avatarRick Hudson <rlh@golang.org>
      Run-TryBot: Austin Clements <austin@google.com>
      TryBot-Result: Gobot Gobot <gobot@golang.org>
      1a2cf91f
    • Keith Randall's avatar
      cmd/compile: a rule's line number is at its -> · 3b0efa68
      Keith Randall authored
      Let's define the line number of a multiline rule as the line
      number on which the -> appears.  This helps make the rule
      cover analysis look a bit nicer.
      
      Change-Id: I4ac4c09f2240285976590ecfd416bc4c05e78946
      Reviewed-on: https://go-review.googlesource.com/22473Reviewed-by: default avatarJosh Bleecher Snyder <josharian@gmail.com>
      3b0efa68