Skip to content

storage/cmdq: create new signal type for cmd completion signaling#32164

Merged
craig[bot] merged 1 commit intocockroachdb:masterfrom
nvb:nvanbenschoten/cmdqSignal
Nov 12, 2018
Merged

storage/cmdq: create new signal type for cmd completion signaling#32164
craig[bot] merged 1 commit intocockroachdb:masterfrom
nvb:nvanbenschoten/cmdqSignal

Conversation

@nvb
Copy link
Copy Markdown
Contributor

@nvb nvb commented Nov 6, 2018

signal is a type that can signal the completion of an operation.
This is a component of the larger change in #31997.

The type has three benefits over using a channel directly and
closing the channel when the operation completes:

  1. signaled() uses atomics to provide a fast-path for checking
    whether the operation has completed. It is ~75x faster than
    using a channel for this purpose.
  2. the type's channel is lazily initialized when signalChan()
    is called, avoiding the allocation when one is not needed.
  3. because of 2, the type's zero value can be used directly.

Release note: None

@nvb nvb requested review from a team and a-robinson November 6, 2018 15:16
@cockroach-teamcity
Copy link
Copy Markdown
Member

This change is Reviewable

@nvb
Copy link
Copy Markdown
Contributor Author

nvb commented Nov 6, 2018

name                       time/op
Signaled-4                 0.33ns ± 4%
SignalBeforeChan-4         10.5ns ± 7%
SignalAfterChan-4          51.5ns ±51%
InitialChanBeforeSignal-4  84.2ns ±11%
SecondChanBeforeSignal-4   2.64ns ± 6%
InitialChanAfterSignal-4   2.94ns ± 3%
SecondChanAfterSignal-4    2.90ns ±35%
ReadClosedChan-4           24.1ns ± 0%
SingleSelectClosedChan-4   25.6ns ± 3%
DefaultSelectClosedChan-4  25.4ns ± 8%
MultiSelectClosedChan-4     101ns ± 3%
AtomicLoad-4               0.43ns ± 2%

name                       alloc/op
Signaled-4                  0.00B
SignalBeforeChan-4          0.00B
SignalAfterChan-4           0.00B
InitialChanBeforeSignal-4   96.0B ± 0%
SecondChanBeforeSignal-4    0.00B
InitialChanAfterSignal-4    0.00B
SecondChanAfterSignal-4     0.00B
ReadClosedChan-4            0.00B
SingleSelectClosedChan-4    0.00B
DefaultSelectClosedChan-4   0.00B
MultiSelectClosedChan-4     0.00B
AtomicLoad-4                0.00B

name                       allocs/op
Signaled-4                   0.00
SignalBeforeChan-4           0.00
SignalAfterChan-4            0.00
InitialChanBeforeSignal-4    1.00 ± 0%
SecondChanBeforeSignal-4     0.00
InitialChanAfterSignal-4     0.00
SecondChanAfterSignal-4      0.00
ReadClosedChan-4             0.00
SingleSelectClosedChan-4     0.00
DefaultSelectClosedChan-4    0.00
MultiSelectClosedChan-4      0.00
AtomicLoad-4                 0.00

@nvb nvb force-pushed the nvanbenschoten/cmdqSignal branch from 0da46f8 to 59717fa Compare November 6, 2018 20:18
Copy link
Copy Markdown
Collaborator

@petermattis petermattis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained


pkg/storage/cmdq/signal.go, line 38 at r1 (raw file):

//    whether the operation has completed. It is ~75x faster than
//    using a channel for this purpose.
// 2. the type's channel is lazily initialized when signalChan()

s/type/receiver/g


pkg/storage/cmdq/signal.go, line 86 at r1 (raw file):

		close(c)
	}
	return c

The returned channel might not be closed even though the signal has been signaled. This seems like a rare scenario, though I'm wondering if we should close it. I think that can be done by adding another sigHalfClosed state:

if atomic.CompareAndSwapInt32(&s.a, sig. sigHalfClosed) {
  close(c)
  atomic.StoreInt32(&s.a, sigClosed)
} else {
  for atomic.LoadInt32(&s.a) == sigHalfClosed {
    runtime.GoSched()
  }
}

You'd wrap this up in a close() method so it could be shared with signal().

signal is a type that can signal the completion of an operation.

The type has three benefits over using a channel directly and
closing the channel when the operation completes:
1. signaled() uses atomics to provide a fast-path for checking
   whether the operation has completed. It is ~75x faster than
   using a channel for this purpose.
2. the type's channel is lazily initialized when signalChan()
   is called, avoiding the allocation when one is not needed.
3. because of 2, the type's zero value can be used directly.

Release note: None
@nvb nvb force-pushed the nvanbenschoten/cmdqSignal branch from 59717fa to a08d232 Compare November 11, 2018 20:43
Copy link
Copy Markdown
Contributor Author

@nvb nvb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained


pkg/storage/cmdq/signal.go, line 38 at r1 (raw file):

Previously, petermattis (Peter Mattis) wrote…

s/type/receiver/g

Done.


pkg/storage/cmdq/signal.go, line 86 at r1 (raw file):

The returned channel might not be closed even though the signal has been signaled.

Is that a problem though? It will be closed immediately after (before signal() returns), and the caller of signalChan will block on the channel either way. It shouldn't be any different than if signalChan is called before signal().

Copy link
Copy Markdown
Member

@tbg tbg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewed 1 of 2 files at r1, 1 of 1 files at r2.
Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained

Copy link
Copy Markdown
Collaborator

@petermattis petermattis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained


pkg/storage/cmdq/signal.go, line 86 at r1 (raw file):

Previously, nvanbenschoten (Nathan VanBenschoten) wrote…

The returned channel might not be closed even though the signal has been signaled.

Is that a problem though? It will be closed immediately after (before signal() returns), and the caller of signalChan will block on the channel either way. It shouldn't be any different than if signalChan is called before signal().

Yeah, I suppose I was overthinking this. Without the atomic the behavior would be the same. Carry on.

@nvb
Copy link
Copy Markdown
Contributor Author

nvb commented Nov 12, 2018

I never mentioned the motivation for this change in the PR description. With the new approach in #31997, we end up "waiting" on a much larger number of prerequisites while iterating over prerequisites. There are two reasons for this:

  1. we don't actively try to ignore transitive dependencies like we do in the current command queue
  2. we don't eagerly pull out dependencies from the tree under lock before beginning to wait

This means that there's a much better chance that we reach prereq cmds that are already finished while iterating over our btree snapshot. This was beginning to show up on cpu profiles when I was testing with #31997, and a change like this made the issue go away entirely.

TFTRs.

bors r+

craig bot pushed a commit that referenced this pull request Nov 12, 2018
32164: storage/cmdq: create new signal type for cmd completion signaling r=nvanbenschoten a=nvanbenschoten

`signal` is a type that can signal the completion of an operation.
This is a component of the larger change in #31997.

The type has three benefits over using a channel directly and
closing the channel when the operation completes:
1. signaled() uses atomics to provide a fast-path for checking
   whether the operation has completed. It is ~75x faster than
   using a channel for this purpose.
2. the type's channel is lazily initialized when signalChan()
   is called, avoiding the allocation when one is not needed.
3. because of 2, the type's zero value can be used directly.

Release note: None

Co-authored-by: Nathan VanBenschoten <nvanbenschoten@gmail.com>
@craig
Copy link
Copy Markdown
Contributor

craig bot commented Nov 12, 2018

Build succeeded

@craig craig bot merged commit a08d232 into cockroachdb:master Nov 12, 2018
@nvb nvb deleted the nvanbenschoten/cmdqSignal branch November 13, 2018 01:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants