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
ConnectBlock: don't serialize block hash twice #23819
Conversation
Concept ACK, will review in the next days. ref: #23724 |
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.
Code-review ACK b60c8fd
Not related to the tracepoint overhead, but maybe still worth mentioning: note that in the PR branch, block.GetHash()
is still called more than once in CChainState::ConnectBlock
, as there is another invocation at the very start:
Line 1869 in a1e04e1
assert(*pindex->phashBlock == block.GetHash()); |
(As far as I know, we enforce compiling with assertions on, i.e. NDEBUG never being set)
b60c8fd
to
8f8b196
Compare
On Sat, Jan 01, 2022 at 01:55:29PM -0800, Sebastian Falbesoner wrote:
Not related to the tracepoint overhead, but maybe still worth mentioning: note that in the PR branch, `block.GetHash()` is still called more than once in `CChainState::ConnectBlock`, as there is another invocation at the very start:
https://github.com/bitcoin/bitcoin/blob/a1e04e10799791a728cce4430808517598c8742c/src/validation.cpp#L1869
(As far as I know, we enforce compiling with assertions on, i.e. NDEBUG never being set)
great catch. I've moved the blockHash variable to above the assert, so we shave off ~16,000 instructions now.
|
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.
Code review re-ACK 8f8b196
Slightly off-topic, but could you elaborate how exactly you measure the number of saved instructions (and on which architecture)? Do you statically analyse the compiled binary or do it dynamically via perf
or alike?
On Tue, Jan 04, 2022 at 10:57:28AM -0800, Sebastian Falbesoner wrote:
Slightly off-topic, but could you elaborate how exactly you measure the number of saved instructions (and on which architecture)? Do you statically analyse the compiled binary or do it dynamically via `perf` or alike?
See #23724 (comment) for the method
and #23724 (comment) for where I determined that GetHash hits 8000 instructions.
|
…ilds with USDT tracepoints 6200fbf build: rename --enable-ebpf to --enable-usdt (0xb10c) e158a2a build: add systemtap's sys/sdt.h as depends (0xb10c) Pull request description: There has been light conceptual agreement on including the Userspace, Statically Defined Tracing tracepoints in Bitcoin Core release builds. This, for example, enables user to hook into production deployments, if they need to. Binaries don't have to be switched out. This is possible because we don't do [expensive computations](https://github.com/bitcoin/bitcoin/blob/master/doc/tracing.md#no-expensive-computations-for-tracepoints) only needed for the tracepoints. The tracepoints are NOPs when not used. Systemtap's `sys/sdt.h` header is required to build Bitcoin Core with USDT support. The header file defines the `DTRACE_PROBE` macros used in [`src/util/trace.h`](https://github.com/bitcoin/bitcoin/blob/master/src/util/trace.h). This PR adds Systemtap 4.5 (May 2021) as dependency. GUIX builds for Linux hosts now include the tracepoints. Closes #23297. ACKs for top commit: fanquake: ACK 6200fbf - tested enabling / disabling and with/without SDT from depends. We can follow up with #23819, #23907 and #23296, and if any serious issues arise before feature freeze, it is easy for us to flip depends such that USDT becomes opt-in, rather than opt-out, and thus, releases would be tracepoint free. Tree-SHA512: 0263f44892bf8450e8a593e4de7a498243687f8d81269e1c3283fa8354922c7cf93fddef4b92cf5192d33798424aa5812e03e68ef8de31af078a32dd34021382
…GUIX builds with USDT tracepoints 6200fbf build: rename --enable-ebpf to --enable-usdt (0xb10c) e158a2a build: add systemtap's sys/sdt.h as depends (0xb10c) Pull request description: There has been light conceptual agreement on including the Userspace, Statically Defined Tracing tracepoints in Bitcoin Core release builds. This, for example, enables user to hook into production deployments, if they need to. Binaries don't have to be switched out. This is possible because we don't do [expensive computations](https://github.com/bitcoin/bitcoin/blob/master/doc/tracing.md#no-expensive-computations-for-tracepoints) only needed for the tracepoints. The tracepoints are NOPs when not used. Systemtap's `sys/sdt.h` header is required to build Bitcoin Core with USDT support. The header file defines the `DTRACE_PROBE` macros used in [`src/util/trace.h`](https://github.com/bitcoin/bitcoin/blob/master/src/util/trace.h). This PR adds Systemtap 4.5 (May 2021) as dependency. GUIX builds for Linux hosts now include the tracepoints. Closes bitcoin#23297. ACKs for top commit: fanquake: ACK 6200fbf - tested enabling / disabling and with/without SDT from depends. We can follow up with bitcoin#23819, bitcoin#23907 and bitcoin#23296, and if any serious issues arise before feature freeze, it is easy for us to flip depends such that USDT becomes opt-in, rather than opt-out, and thus, releases would be tracepoint free. Tree-SHA512: 0263f44892bf8450e8a593e4de7a498243687f8d81269e1c3283fa8354922c7cf93fddef4b92cf5192d33798424aa5812e03e68ef8de31af078a32dd34021382
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.
utACK
I'm surprised we're not caching block hashes like we do for transactions, though?
On Tue, Jan 11, 2022 at 03:11:55PM -0800, Luke Dashjr wrote:
I'm surprised we're not caching block hashes like we do for transactions, though?
Where is it cached for transactions? I see `CMutableTransaction::GetHash` but it looks roughly the same as `CBlockHeader::GetHash`.
|
Check |
On Tue, Jan 11, 2022 at 05:03:06PM -0800, Luke Dashjr wrote:
Check `CTransaction`
gotcha, I see ComputeHash in the constructor. Yes it looks like CBlockHeader doesn't have caching, I'm guessing because it's a mutable thing?
|
Looks like this is also refactoring |
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.
lgtm. Left a style nit
In the validation:block_connected tracepoint, we call block->GetHash(), which ends up calling CBlockHeader::GetHash(), executing around 8000 serialization instructions. We don't need to do this extra work, because block->GetHash() is already called further up in the function. Let's save that value as a local variable and re-use it in our tracepoint so there is no unnecessary tracepoint overhead. Signed-off-by: William Casarin <jb55@jb55.com>
Shave off an extra 100 or so instructions from the validation:block_connected tracepoint by reusing a nearby GetTimeMicros(). This brings the tracepoint down to 54 instructions. Still high, but much better than the previous ~154 and 8000 instructions which it was originally. Signed-off-by: William Casarin <jb55@jb55.com>
8f8b196
to
eb8b22d
Compare
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.
re-ACK eb8b22d
ACK eb8b22d I'm measuring 7 instructions. Code changes look good to me. Still needs refactoring in the PR title :)
@jb55 you mention 54 instructions in eb8b22d. I think your measurements include the instructions from line 2161. I'm starting the measurement in line 2163. Lines 2161 to 2172 in eb8b22d
|
Code review ACK eb8b22d |
…ash twice (#5042) * block_connected: don't serialize block hash twice In the validation:block_connected tracepoint, we call block->GetHash(), which ends up calling CBlockHeader::GetHash(), executing around 8000 serialization instructions. We don't need to do this extra work, because block->GetHash() is already called further up in the function. Let's save that value as a local variable and re-use it in our tracepoint so there is no unnecessary tracepoint overhead. Signed-off-by: William Casarin <jb55@jb55.com> * ConnectBlock: re-use hash on budget start Signed-off-by: William Casarin <jb55@jb55.com> Co-authored-by: William Casarin <jb55@jb55.com>
Summary: ``` In the validation:block_connected tracepoint, we call block->GetHash(), which ends up calling CBlockHeader::GetHash(), executing around 8000 serialization instructions. We don't need to do this extra work, because block->GetHash() is already called further up in the function. Let's save that value as a local variable and re-use it in our tracepoint so there is no unnecessary tracepoint overhead. Shave off an extra 100 or so instructions from the validation:block_connected tracepoint by reusing a nearby GetTimeMicros(). This brings the tracepoint down to 54 instructions. Still high, but much better than the previous ~154 and 8000 instructions which it was originally. ``` Backport of [[bitcoin/bitcoin#23819 | core#23819]]. Depends on D12674. Test Plan: sudo bpftrace ../contrib/tracing/connectblock_benchmark.bt 0 0 25 Reviewers: #bitcoin_abc, PiRK, sdulfari Reviewed By: #bitcoin_abc, PiRK, sdulfari Differential Revision: https://reviews.bitcoinabc.org/D12705
In the validation:block_connected tracepoint, we call block->GetHash(), which
ends up calling CBlockHeader::GetHash(), executing around 8000 serialization
instructions. We don't need to do this extra work, because block->GetHash() is
already called further up in the function. Let's save that value as a local
variable and re-use it in our tracepoint so there is no unnecessary tracepoint
overhead.
Shave off an extra 100 or so instructions from the validation:block_connected
tracepoint by reusing a nearby GetTimeMicros(). This brings the tracepoint down
to 54 instructions. Still high, but much better than the previous ~154 and
8000 instructions which it was originally.
Signed-off-by: William Casarin jb55@jb55.com