tracing: cast block_connected duration to nanoseconds

When the tracepoint was introduced in 8f37f5c2a5,
the connect_block duration was passed in microseconds `µs`.
By starting to use steady clock in fabf1cdb20
this changed to nanoseconds `ns`. As the test only checked if the
duration value is `> 0` as a plausibility check, this went unnoticed.

I detected this when setting up monitoring for block validation time
as part of the Great Consensus Cleanup Revival discussion.

This change casts the duration explicitly to nanoseconds (as it has been
nanoseconds for the last three releases; switching back now would 'break'
the broken API again; there don't seem to be many users affected), updates
the documentation and adds a check for an upper bound to the tracepoint
interface tests. The upper bound is quite lax as mining the block takes
much longer than connecting the empty test block. It's however able to
detect incorrect duration units passed.
pull/29877/head
0xb10c 7 months ago
parent 9cb9651d92
commit cd0edf26c0
No known key found for this signature in database
GPG Key ID: E2FFD5B1D88CA97D

@ -82,7 +82,7 @@ usdt:./build/src/bitcoind:validation:block_connected /arg1 >= $1 && (arg1 <= $2
@inputs = @inputs + $inputs; @inputs = @inputs + $inputs;
@sigops = @sigops + $sigops; @sigops = @sigops + $sigops;
@durations = hist($duration / 1000); @durations = hist($duration / 1e6);
if ($height == $1 && $height != 0) { if ($height == $1 && $height != 0) {
@start = nsecs; @start = nsecs;
@ -92,7 +92,7 @@ usdt:./build/src/bitcoind:validation:block_connected /arg1 >= $1 && (arg1 <= $2
if ($2 > 0 && $height >= $2) { if ($2 > 0 && $height >= $2) {
@end = nsecs; @end = nsecs;
$duration = @end - @start; $duration = @end - @start;
printf("\nTook %d ms to connect the blocks between height %d and %d.\n", $duration / 1000000, $1, $2); printf("\nTook %d ms to connect the blocks between height %d and %d.\n", $duration / 1e9, $1, $2);
exit(); exit();
} }
} }
@ -102,7 +102,7 @@ usdt:./build/src/bitcoind:validation:block_connected /arg1 >= $1 && (arg1 <= $2
blocks where the time it took to connect the block is above the blocks where the time it took to connect the block is above the
<logging threshold in ms>. <logging threshold in ms>.
*/ */
usdt:./build/src/bitcoind:validation:block_connected / (uint64) arg5 / 1000> $3 / usdt:./build/src/bitcoind:validation:block_connected / (uint64) arg5 / 1e6 > $3 /
{ {
$hash = arg0; $hash = arg0;
$height = (int32) arg1; $height = (int32) arg1;
@ -120,7 +120,7 @@ usdt:./build/src/bitcoind:validation:block_connected / (uint64) arg5 / 1000> $3
printf("%02x", $b); printf("%02x", $b);
$p -= 1; $p -= 1;
} }
printf(") %4d tx %5d ins %5d sigops took %4d ms\n", $transactions, $inputs, $sigops, (uint64) $duration / 1000); printf(") %4d tx %5d ins %5d sigops took %4d ms\n", $transactions, $inputs, $sigops, (uint64) $duration / 1e6);
} }

@ -106,7 +106,7 @@ Arguments passed:
3. Transactions in the Block as `uint64` 3. Transactions in the Block as `uint64`
4. Inputs spend in the Block as `int32` 4. Inputs spend in the Block as `int32`
5. SigOps in the Block (excluding coinbase SigOps) `uint64` 5. SigOps in the Block (excluding coinbase SigOps) `uint64`
6. Time it took to connect the Block in microseconds (µs) as `uint64` 6. Time it took to connect the Block in nanoseconds (ns) as `uint64`
### Context `utxocache` ### Context `utxocache`

@ -2738,7 +2738,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
block.vtx.size(), block.vtx.size(),
nInputs, nInputs,
nSigOpsCost, nSigOpsCost,
time_5 - time_start // in microseconds (µs) Ticks<std::chrono::nanoseconds>(time_5 - time_start)
); );
return true; return true;

@ -8,6 +8,7 @@
""" """
import ctypes import ctypes
import time
# Test will be skipped if we don't have bcc installed # Test will be skipped if we don't have bcc installed
try: try:
@ -105,10 +106,12 @@ class ValidationTracepointTest(BitcoinTestFramework):
handle_blockconnected) handle_blockconnected)
self.log.info(f"mine {BLOCKS_EXPECTED} blocks") self.log.info(f"mine {BLOCKS_EXPECTED} blocks")
block_hashes = self.generatetoaddress( generatetoaddress_duration = dict()
self.nodes[0], BLOCKS_EXPECTED, ADDRESS_BCRT1_UNSPENDABLE) for _ in range(BLOCKS_EXPECTED):
for block_hash in block_hashes: start = time.time()
expected_blocks[block_hash] = self.nodes[0].getblock(block_hash, 2) hash = self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_UNSPENDABLE)[0]
generatetoaddress_duration[hash] = (time.time() - start) * 1e9 # in nanoseconds
expected_blocks[hash] = self.nodes[0].getblock(hash, 2)
bpf.perf_buffer_poll(timeout=200) bpf.perf_buffer_poll(timeout=200)
@ -123,6 +126,10 @@ class ValidationTracepointTest(BitcoinTestFramework):
assert_equal(0, event.sigops) # no sigops in coinbase tx assert_equal(0, event.sigops) # no sigops in coinbase tx
# only plausibility checks # only plausibility checks
assert event.duration > 0 assert event.duration > 0
# generatetoaddress (mining and connecting) takes longer than
# connecting the block. In case the duration unit is off, we'll
# detect it with this assert.
assert event.duration < generatetoaddress_duration[block_hash]
del expected_blocks[block_hash] del expected_blocks[block_hash]
assert_equal(BLOCKS_EXPECTED, len(events)) assert_equal(BLOCKS_EXPECTED, len(events))
assert_equal(0, len(expected_blocks)) assert_equal(0, len(expected_blocks))

Loading…
Cancel
Save