Skip to content

Conversation

eklitzke
Copy link
Contributor

@eklitzke eklitzke commented Mar 6, 2018

Today I came across #10271, and while reading the discussion #6358 was linked to. Linux systems have a SCHED_BATCH scheduler priority that is useful for threads like loadblk. You can find the full details at sched(7), but I'll quote the relevant part of the man page below:

...this policy will cause the scheduler to always assume that the thread is
CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
with respect to wakeup behavior, so that this thread is mildly disfavored in
scheduling decisions.

This policy is useful for workloads that are noninteractive, but do not want to
lower their nice value, and for workloads that want a deterministic scheduling
policy without interactivity causing extra preemptions (between the workload's
tasks).

I think this change is useful independently of #10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import mempool.dat. However, if Bitcoin is started with -reindex or -reindex-chainstate this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of -reindex). By setting SCHED_BATCH this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using ioprio_set(2) because it can cause the thread to become completely I/O starved (and knowledgeable users can use ionice(1) anyway).

src/util.cpp Outdated
@@ -955,3 +955,10 @@ fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific)
{
return fs::absolute(path, GetDataDir(net_specific));
}

void ScheduleBatchPriority(pid_t tid) {
Copy link
Member

Choose a reason for hiding this comment

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

pid_t is not available on windows, I think it would be better to remove the parameter as it's always passed as 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you're right.

@laanwj
Copy link
Member

laanwj commented Mar 6, 2018

Is loadblk thread the only thread this is relevant for? what about the script verification threads?

@promag
Copy link
Contributor

promag commented Mar 6, 2018

Is this the windows equivalent?

SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN)

@eklitzke
Copy link
Contributor Author

eklitzke commented Mar 6, 2018

On Linux SCHED_BATCH just prevents batch tasks from pre-empting normal tasks (i.e. normal tasks will run until their timeslice expires, or another normal tasks pre-empts them). When picking the next task to run the scheduler considers SCHED_OTHER (i.e. normal) and SCHED_BATCH tasks equally. This is why setting SCHED_BATCH tasks are only "mildly disfavored", because they'll still be considered to run using the normal metrics whenever the scheduler ticks (usually 100Hz or 1000Hz).

It sounds like Windows THREAD_MODE_BACKGROUND_BEGIN is much more extreme. It looks like maybe the Windows equivalent is THREAD_PRIORITY_BELOW_NORMAL but I do not know a lot about Windows.

I don't know as much about the script verification threads. If we are going to set SCHED_BATCH for loadblk then it makes sense to me to set the script verification threads to SCHED_BATCH as well, at least until the loadblk thread completes. You can freely switch back from SCHED_BATCH to SCHED_OTHER so it would be possible to only run them in the batch mode while reindexing is happening, or we could just always have them set at batch priority.

@JeremyRubin
Copy link
Contributor

Concept ACK for this:

one note: you would want something realtime for scriptcheck threads while they are validating a block incoming from network -- we want these to take priority over other threads aggressively.

@eklitzke
Copy link
Contributor Author

eklitzke commented Mar 9, 2018

Re: Jeremy's comment, there are a few ways to increase the priority of the script verification thread to ensure low-latency block relay. On Linux there exists SCHED_FIFO and SCHED_RR threads which give threads semi-realtime scheduling guarantees, and can ensure that such threads are always prioritized above other threads. Linux also supports per-thread nice values (this is a Linux extension, POSIX specifies that nice values are per-process).

Using the other scheduling modes is better for realtime behavior, but somewhat dangerous because such threads can pre-empt all other non-realtime processes, meaning that this could be used as a DOS vector. Changing the nice value is a bit safer. I will probably look into this as part of another PR because I'd like to benchmark that change.

@maflcko
Copy link
Member

maflcko commented Mar 18, 2018

I think the commits can be squashed?

@eklitzke
Copy link
Contributor Author

Thanks @MarcoFalke , squashed to one commit. I'm interested into looking at the RT change Jeremy suggested as well, but that's more impactful so I'd rather do that separately unless people want to see that change done here.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

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

utACK a2ed276b52aec97d37257b7aad73f7f332a926d3

@@ -627,6 +627,7 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
{
const CChainParams& chainparams = Params();
RenameThread("bitcoin-loadblk");
ScheduleBatchPriority();
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be nice to log the error message if sched_batch returns -1. EINVAL / EPERM cases would be good to know about.

src/util.cpp Outdated
int ScheduleBatchPriority(void) {
#if HAVE_SCHED_H && defined(SCHED_BATCH)
sched_param param{.sched_priority = 0};
return sched_setscheduler(0, SCHED_BATCH, &param);
Copy link
Contributor

Choose a reason for hiding this comment

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

Would calling pthread_setschedparam instead of sched_setscheduler be a little more portable? It seems like you might not need the configure check using this.

@eklitzke eklitzke force-pushed the sched_batch branch 3 times, most recently from 0d5541e to 8fe7e95 Compare March 26, 2018 22:55
@eklitzke
Copy link
Contributor Author

Updated to use pthread_setschedparam(). It seems that <sched.h> is standard on Posix systems but SCHED_BATCH is not, so I updated the #ifdef logic a little to reflect that. I also put the error logging in SchedBatchPriority() itself as this return 1 on Windows but errno won't be set. Could also do it the other way (return 0 on non-Linux hosts and then move the log statement to the call site).

While reading another PR I saw a mention of bitcoin#6358. The use case for
SCHED_BATCH is to hint to the kernel that the thread is running a
non-interactive workload that consumes a lot of CPU time. This is
helpful on desktop machines where the loadblk thread can interfere with
interactive applications. More details can be found in the sched(7) man
page.
@laanwj
Copy link
Member

laanwj commented Apr 7, 2018

utACK d54874d

@laanwj laanwj merged commit d54874d into bitcoin:master Apr 7, 2018
laanwj added a commit that referenced this pull request Apr 7, 2018
d54874d Set SCHED_BATCH priority on the loadblk thread. (Evan Klitzke)

Pull request description:

  Today I came across #10271, and while reading the discussion #6358 was linked to. Linux systems have a `SCHED_BATCH` scheduler priority that is useful for threads like loadblk. You can find the full details at [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html), but I'll quote the relevant part of the man page below:

  > ...this policy will cause the scheduler to always assume that the thread is
  CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
  with respect to wakeup behavior, so that this thread is mildly disfavored in
  scheduling decisions.
  >
  > This policy is useful for workloads that are noninteractive, but do not want to
  lower their nice value, and for workloads that want a deterministic scheduling
  policy without interactivity causing extra preemptions (between the workload's
  tasks).

  I think this change is useful independently of #10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import `mempool.dat`. However, if Bitcoin is started with `-reindex` or `-reindex-chainstate` this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of `-reindex`). By setting `SCHED_BATCH` this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

  I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using [ioprio_set(2)](http://man7.org/linux/man-pages/man2/ioprio_set.2.html) because it can cause the thread to become completely I/O starved (and knowledgeable users can use `ionice(1)` anyway).

Tree-SHA512: ea8f7d3921ed5708948809da771345cdc33efd7ba3323e9dfec07a25bc21e8612e2676f9c178e2710c7bc437e8c9cafc5e0463613688fea5699b6e8e2fec6cff
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Aug 30, 2019
Summary:
d54874d Set SCHED_BATCH priority on the loadblk thread. (Evan Klitzke)

Pull request description:

  Today I came across #10271, and while reading the discussion #6358 was linked to. Linux systems have a `SCHED_BATCH` scheduler priority that is useful for threads like loadblk. You can find the full details at [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html), but I'll quote the relevant part of the man page below:

  > ...this policy will cause the scheduler to always assume that the thread is
  CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
  with respect to wakeup behavior, so that this thread is mildly disfavored in
  scheduling decisions.
  >
  > This policy is useful for workloads that are noninteractive, but do not want to
  lower their nice value, and for workloads that want a deterministic scheduling
  policy without interactivity causing extra preemptions (between the workload's
  tasks).

  I think this change is useful independently of #10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import `mempool.dat`. However, if Bitcoin is started with `-reindex` or `-reindex-chainstate` this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of `-reindex`). By setting `SCHED_BATCH` this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

  I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using [ioprio_set(2)](http://man7.org/linux/man-pages/man2/ioprio_set.2.html) because it can cause the thread to become completely I/O starved (and knowledgeable users can use `ionice(1)` anyway).

Tree-SHA512: ea8f7d3921ed5708948809da771345cdc33efd7ba3323e9dfec07a25bc21e8612e2676f9c178e2710c7bc437e8c9cafc5e0463613688fea5699b6e8e2fec6cff

Backport of Core PR12618
bitcoin/bitcoin#12618

Test Plan:
  make check
  test_runner.py

Reviewers: deadalnix, Fabien, jasonbcox, O1 Bitcoin ABC, #bitcoin_abc

Reviewed By: deadalnix, O1 Bitcoin ABC, #bitcoin_abc

Differential Revision: https://reviews.bitcoinabc.org/D3953
jonspock pushed a commit to jonspock/devault that referenced this pull request Dec 8, 2019
Summary:
d54874d Set SCHED_BATCH priority on the loadblk thread. (Evan Klitzke)

Pull request description:

  Today I came across #10271, and while reading the discussion #6358 was linked to. Linux systems have a `SCHED_BATCH` scheduler priority that is useful for threads like loadblk. You can find the full details at [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html), but I'll quote the relevant part of the man page below:

  > ...this policy will cause the scheduler to always assume that the thread is
  CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
  with respect to wakeup behavior, so that this thread is mildly disfavored in
  scheduling decisions.
  >
  > This policy is useful for workloads that are noninteractive, but do not want to
  lower their nice value, and for workloads that want a deterministic scheduling
  policy without interactivity causing extra preemptions (between the workload's
  tasks).

  I think this change is useful independently of #10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import `mempool.dat`. However, if Bitcoin is started with `-reindex` or `-reindex-chainstate` this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of `-reindex`). By setting `SCHED_BATCH` this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

  I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using [ioprio_set(2)](http://man7.org/linux/man-pages/man2/ioprio_set.2.html) because it can cause the thread to become completely I/O starved (and knowledgeable users can use `ionice(1)` anyway).

Tree-SHA512: ea8f7d3921ed5708948809da771345cdc33efd7ba3323e9dfec07a25bc21e8612e2676f9c178e2710c7bc437e8c9cafc5e0463613688fea5699b6e8e2fec6cff

Backport of Core PR12618
bitcoin/bitcoin#12618

Test Plan:
  make check
  test_runner.py

Reviewers: deadalnix, Fabien, jasonbcox, O1 Bitcoin ABC, #bitcoin_abc

Reviewed By: deadalnix, O1 Bitcoin ABC, #bitcoin_abc

Differential Revision: https://reviews.bitcoinabc.org/D3953
jonspock pushed a commit to jonspock/devault that referenced this pull request Dec 8, 2019
Summary:
d54874d Set SCHED_BATCH priority on the loadblk thread. (Evan Klitzke)

Pull request description:

  Today I came across #10271, and while reading the discussion #6358 was linked to. Linux systems have a `SCHED_BATCH` scheduler priority that is useful for threads like loadblk. You can find the full details at [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html), but I'll quote the relevant part of the man page below:

  > ...this policy will cause the scheduler to always assume that the thread is
  CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
  with respect to wakeup behavior, so that this thread is mildly disfavored in
  scheduling decisions.
  >
  > This policy is useful for workloads that are noninteractive, but do not want to
  lower their nice value, and for workloads that want a deterministic scheduling
  policy without interactivity causing extra preemptions (between the workload's
  tasks).

  I think this change is useful independently of #10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import `mempool.dat`. However, if Bitcoin is started with `-reindex` or `-reindex-chainstate` this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of `-reindex`). By setting `SCHED_BATCH` this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

  I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using [ioprio_set(2)](http://man7.org/linux/man-pages/man2/ioprio_set.2.html) because it can cause the thread to become completely I/O starved (and knowledgeable users can use `ionice(1)` anyway).

Tree-SHA512: ea8f7d3921ed5708948809da771345cdc33efd7ba3323e9dfec07a25bc21e8612e2676f9c178e2710c7bc437e8c9cafc5e0463613688fea5699b6e8e2fec6cff

Backport of Core PR12618
bitcoin/bitcoin#12618

Test Plan:
  make check
  test_runner.py

Reviewers: deadalnix, Fabien, jasonbcox, O1 Bitcoin ABC, #bitcoin_abc

Reviewed By: deadalnix, O1 Bitcoin ABC, #bitcoin_abc

Differential Revision: https://reviews.bitcoinabc.org/D3953
jonspock pushed a commit to jonspock/devault that referenced this pull request Dec 8, 2019
Summary:
d54874d Set SCHED_BATCH priority on the loadblk thread. (Evan Klitzke)

Pull request description:

  Today I came across #10271, and while reading the discussion #6358 was linked to. Linux systems have a `SCHED_BATCH` scheduler priority that is useful for threads like loadblk. You can find the full details at [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html), but I'll quote the relevant part of the man page below:

  > ...this policy will cause the scheduler to always assume that the thread is
  CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
  with respect to wakeup behavior, so that this thread is mildly disfavored in
  scheduling decisions.
  >
  > This policy is useful for workloads that are noninteractive, but do not want to
  lower their nice value, and for workloads that want a deterministic scheduling
  policy without interactivity causing extra preemptions (between the workload's
  tasks).

  I think this change is useful independently of #10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import `mempool.dat`. However, if Bitcoin is started with `-reindex` or `-reindex-chainstate` this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of `-reindex`). By setting `SCHED_BATCH` this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

  I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using [ioprio_set(2)](http://man7.org/linux/man-pages/man2/ioprio_set.2.html) because it can cause the thread to become completely I/O starved (and knowledgeable users can use `ionice(1)` anyway).

Tree-SHA512: ea8f7d3921ed5708948809da771345cdc33efd7ba3323e9dfec07a25bc21e8612e2676f9c178e2710c7bc437e8c9cafc5e0463613688fea5699b6e8e2fec6cff

Backport of Core PR12618
bitcoin/bitcoin#12618

Test Plan:
  make check
  test_runner.py

Reviewers: deadalnix, Fabien, jasonbcox, O1 Bitcoin ABC, #bitcoin_abc

Reviewed By: deadalnix, O1 Bitcoin ABC, #bitcoin_abc

Differential Revision: https://reviews.bitcoinabc.org/D3953
proteanx pushed a commit to devaultcrypto/devault that referenced this pull request Dec 12, 2019
Summary:
d54874d Set SCHED_BATCH priority on the loadblk thread. (Evan Klitzke)

Pull request description:

  Today I came across #10271, and while reading the discussion #6358 was linked to. Linux systems have a `SCHED_BATCH` scheduler priority that is useful for threads like loadblk. You can find the full details at [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html), but I'll quote the relevant part of the man page below:

  > ...this policy will cause the scheduler to always assume that the thread is
  CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
  with respect to wakeup behavior, so that this thread is mildly disfavored in
  scheduling decisions.
  >
  > This policy is useful for workloads that are noninteractive, but do not want to
  lower their nice value, and for workloads that want a deterministic scheduling
  policy without interactivity causing extra preemptions (between the workload's
  tasks).

  I think this change is useful independently of #10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import `mempool.dat`. However, if Bitcoin is started with `-reindex` or `-reindex-chainstate` this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of `-reindex`). By setting `SCHED_BATCH` this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

  I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using [ioprio_set(2)](http://man7.org/linux/man-pages/man2/ioprio_set.2.html) because it can cause the thread to become completely I/O starved (and knowledgeable users can use `ionice(1)` anyway).

Tree-SHA512: ea8f7d3921ed5708948809da771345cdc33efd7ba3323e9dfec07a25bc21e8612e2676f9c178e2710c7bc437e8c9cafc5e0463613688fea5699b6e8e2fec6cff

Backport of Core PR12618
bitcoin/bitcoin#12618

Test Plan:
  make check
  test_runner.py

Reviewers: deadalnix, Fabien, jasonbcox, O1 Bitcoin ABC, #bitcoin_abc

Reviewed By: deadalnix, O1 Bitcoin ABC, #bitcoin_abc

Differential Revision: https://reviews.bitcoinabc.org/D3953
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Dec 16, 2020
d54874d Set SCHED_BATCH priority on the loadblk thread. (Evan Klitzke)

Pull request description:

  Today I came across bitcoin#10271, and while reading the discussion dashpay#6358 was linked to. Linux systems have a `SCHED_BATCH` scheduler priority that is useful for threads like loadblk. You can find the full details at [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html), but I'll quote the relevant part of the man page below:

  > ...this policy will cause the scheduler to always assume that the thread is
  CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
  with respect to wakeup behavior, so that this thread is mildly disfavored in
  scheduling decisions.
  >
  > This policy is useful for workloads that are noninteractive, but do not want to
  lower their nice value, and for workloads that want a deterministic scheduling
  policy without interactivity causing extra preemptions (between the workload's
  tasks).

  I think this change is useful independently of bitcoin#10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import `mempool.dat`. However, if Bitcoin is started with `-reindex` or `-reindex-chainstate` this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of `-reindex`). By setting `SCHED_BATCH` this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

  I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using [ioprio_set(2)](http://man7.org/linux/man-pages/man2/ioprio_set.2.html) because it can cause the thread to become completely I/O starved (and knowledgeable users can use `ionice(1)` anyway).

Tree-SHA512: ea8f7d3921ed5708948809da771345cdc33efd7ba3323e9dfec07a25bc21e8612e2676f9c178e2710c7bc437e8c9cafc5e0463613688fea5699b6e8e2fec6cff
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Dec 18, 2020
d54874d Set SCHED_BATCH priority on the loadblk thread. (Evan Klitzke)

Pull request description:

  Today I came across bitcoin#10271, and while reading the discussion dashpay#6358 was linked to. Linux systems have a `SCHED_BATCH` scheduler priority that is useful for threads like loadblk. You can find the full details at [sched(7)](http://man7.org/linux/man-pages/man7/sched.7.html), but I'll quote the relevant part of the man page below:

  > ...this policy will cause the scheduler to always assume that the thread is
  CPU-intensive. Consequently, the scheduler will apply a small scheduling penalty
  with respect to wakeup behavior, so that this thread is mildly disfavored in
  scheduling decisions.
  >
  > This policy is useful for workloads that are noninteractive, but do not want to
  lower their nice value, and for workloads that want a deterministic scheduling
  policy without interactivity causing extra preemptions (between the workload's
  tasks).

  I think this change is useful independently of bitcoin#10271 and irrespective of whether that change is merged. Under normal operation the loadblk thread will just import `mempool.dat`. However, if Bitcoin is started with `-reindex` or `-reindex-chainstate` this thread will use a great deal of CPU while it rebuilds the chainstate database (and the block database in the case of `-reindex`). By setting `SCHED_BATCH` this thread is less likely to interfere with interactive tasks (e.g. the user's web browser, text editor, etc.).

  I'm leaving the nice value unchanged (which also affects scheduling decisions) because I think that's better set by the user. Likewise I'm not using [ioprio_set(2)](http://man7.org/linux/man-pages/man2/ioprio_set.2.html) because it can cause the thread to become completely I/O starved (and knowledgeable users can use `ionice(1)` anyway).

Tree-SHA512: ea8f7d3921ed5708948809da771345cdc33efd7ba3323e9dfec07a25bc21e8612e2676f9c178e2710c7bc437e8c9cafc5e0463613688fea5699b6e8e2fec6cff
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants