Skip to content

Commit 2bc51c5

Browse files
committed
[tracing] tracepoints to utxocache add, spent and uncache
Signed-off-by: Arnab Sen <[email protected]>
1 parent a26e8ee commit 2bc51c5

File tree

6 files changed

+208
-10
lines changed

6 files changed

+208
-10
lines changed

contrib/tracing/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,62 @@ Histogram of block connection times in milliseconds (ms).
234234
[16, 32) 9 | |
235235
[32, 64) 4 | |
236236
```
237+
238+
### log_utxocache_flush.py
239+
240+
A BCC Python script to log the cache and index flushes. Based on the
241+
`utxocache:flush` tracepoint.
242+
243+
```bash
244+
$ python3 contrib/tracing/log_utxocache_flush.py ./src/bitcoind
245+
```
246+
247+
```
248+
Logging utxocache flushes. Ctrl-C to end...
249+
Duration (µs) Mode Coins Count Memory Usage Prune Full Flush
250+
0 PERIODIC 28484 3929.87 kB False False
251+
1 PERIODIC 28485 3930.00 kB False False
252+
0 PERIODIC 28489 3930.51 kB False False
253+
1 PERIODIC 28490 3930.64 kB False False
254+
0 PERIODIC 28491 3930.77 kB False False
255+
0 PERIODIC 28491 3930.77 kB False False
256+
0 PERIODIC 28496 3931.41 kB False False
257+
1 PERIODIC 28496 3931.41 kB False False
258+
0 PERIODIC 28497 3931.54 kB False False
259+
1 PERIODIC 28497 3931.54 kB False False
260+
1 PERIODIC 28499 3931.79 kB False False
261+
.
262+
.
263+
.
264+
53788 ALWAYS 30076 4136.27 kB False False
265+
7463 ALWAYS 0 245.84 kB False False
266+
```
267+
268+
### log_utxos.bt
269+
270+
A `bpftrace` script to log information about the coins that are added, spent, or
271+
uncached from the UTXO set. Based on the `utxocache:add`, `utxocache:spend` and
272+
`utxocache:uncache` tracepoints.
273+
274+
```bash
275+
$ bpftrace contrib/tracing/log_utxos.bt
276+
```
277+
278+
It should produce an output similar to the following.
279+
280+
```bash
281+
Attaching 4 probes...
282+
OP Outpoint Value Height Coinbase
283+
Added 6ba9ad857e1ef2eb2a2c94f06813c414c7ab273e3d6bd7ad64e000315a887e7c:1 10000 2094512 No
284+
Spent fa7dc4db56637a151f6649d8f26732956d1c5424c82aae400a83d02b2cc2c87b:0 182264897 2094512 No
285+
Added eeb2f099b1af6a2a12e6ddd2eeb16fc5968582241d7f08ba202d28b60ac264c7:0 10000 2094512 No
286+
Added eeb2f099b1af6a2a12e6ddd2eeb16fc5968582241d7f08ba202d28b60ac264c7:1 182254756 2094512 No
287+
Added a0c7f4ec9cccef2d89672a624a4e6c8237a17572efdd4679eea9e9ee70d2db04:0 10072679 2094513 Yes
288+
Spent 25e0df5cc1aeb1b78e6056bf403e5e8b7e41f138060ca0a50a50134df0549a5e:2 540 2094508 No
289+
Spent 42f383c04e09c26a2378272ec33aa0c1bf4883ca5ab739e8b7e06be5a5787d61:1 3848399 2007724 No
290+
Added f85e3b4b89270863a389395cc9a4123e417ab19384cef96533c6649abd6b0561:0 3788399 2094513 No
291+
Added f85e3b4b89270863a389395cc9a4123e417ab19384cef96533c6649abd6b0561:2 540 2094513 No
292+
Spent a05880b8c77971ed0b9f73062c7c4cdb0ff3856ab14cbf8bc481ed571cd34b83:1 5591281046 2094511 No
293+
Added eb689865f7d957938978d6207918748f74e6aa074f47874724327089445b0960:0 5589696005 2094513 No
294+
Added eb689865f7d957938978d6207918748f74e6aa074f47874724327089445b0960:1 1565556 2094513 No
295+
```

contrib/tracing/log_utxocache_flush.py

100644100755
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import ctypes
55
from bcc import BPF, USDT
66

7-
""" Example script to log details about coins flushed by the Bitcoin client
8-
utilizing USDT probes and the flush:flush tracepoint. """
7+
"""Example logging Bitcoin Core utxo set cache flushes utilizing
8+
the utxocache:flush tracepoint."""
99

1010
# USAGE: ./contrib/tracing/log_utxocache_flush.py path/to/bitcoind
1111

@@ -22,8 +22,10 @@
2222
bool is_flush_prune;
2323
bool is_full_flush;
2424
};
25+
2526
// BPF perf buffer to push the data to user space.
2627
BPF_PERF_OUTPUT(flush);
28+
2729
int trace_flush(struct pt_regs *ctx) {
2830
struct data_t data = {};
2931
bpf_usdt_readarg(1, ctx, &data.duration);
@@ -45,8 +47,8 @@
4547
]
4648

4749

48-
# define output data structure
4950
class Data(ctypes.Structure):
51+
# define output data structure corresponding to struct data_t
5052
_fields_ = [
5153
("duration", ctypes.c_uint64),
5254
("mode", ctypes.c_uint32),

contrib/tracing/log_utxos.bt

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env bpftrace
2+
3+
/*
4+
5+
USAGE:
6+
7+
bpftrace contrib/tracing/log_utxos.bt
8+
9+
This script requires a 'bitcoind' binary compiled with eBPF support and the
10+
'utxochache' tracepoints. By default, it's assumed that 'bitcoind' is
11+
located in './src/bitcoind'. This can be modified in the script below.
12+
13+
NOTE: requires bpftrace v0.12.0 or above.
14+
*/
15+
16+
BEGIN
17+
{
18+
printf("%-7s %-71s %16s %7s %8s\n",
19+
"OP", "Outpoint", "Value", "Height", "Coinbase");
20+
}
21+
22+
/*
23+
Attaches to the 'utxocache:add' tracepoint and prints additions to the UTXO set cache.
24+
*/
25+
usdt:./src/bitcoind:utxocache:add
26+
{
27+
$txid = arg0;
28+
$index = (uint32)arg1;
29+
$height = (uint32)arg2;
30+
$value = (int64)arg3;
31+
$isCoinbase = arg4;
32+
33+
printf("Added ");
34+
$p = $txid + 31;
35+
unroll(32) {
36+
$b = *(uint8*)$p;
37+
printf("%02x", $b);
38+
$p-=1;
39+
}
40+
41+
printf(":%-6d %16ld %7d %s\n", $index, $value, $height, ($isCoinbase ? "Yes" : "No" ));
42+
}
43+
44+
/*
45+
Attaches to the 'utxocache:spent' tracepoint and prints spents from the UTXO set cache.
46+
*/
47+
usdt:./src/bitcoind:utxocache:spent
48+
{
49+
$txid = arg0;
50+
$index = (uint32)arg1;
51+
$height = (uint32)arg2;
52+
$value = (int64)arg3;
53+
$isCoinbase = arg4;
54+
55+
printf("Spent ");
56+
$p = $txid + 31;
57+
unroll(32) {
58+
$b = *(uint8*)$p;
59+
printf("%02x", $b);
60+
$p-=1;
61+
}
62+
63+
printf(":%-6d %16ld %7d %s\n", $index, $value, $height, ($isCoinbase ? "Yes" : "No" ));
64+
}
65+
66+
/*
67+
Attaches to the 'utxocache:uncache' tracepoint and uncache UTXOs from the UTXO set cache.
68+
*/
69+
usdt:./src/bitcoind:utxocache:uncache
70+
{
71+
$txid = arg0;
72+
$index = (uint32)arg1;
73+
$height = (uint32)arg2;
74+
$value = (int64)arg3;
75+
$isCoinbase = arg4;
76+
77+
printf("Uncache ");
78+
$p = $txid + 31;
79+
unroll(32) {
80+
$b = *(uint8*)$p;
81+
printf("%02x", $b);
82+
$p-=1;
83+
}
84+
85+
printf(":%-6d %16ld %7d %s\n", $index, $value, $height, ($isCoinbase ? "Yes" : "No" ));
86+
}

doc/tracing.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,39 @@ Arguments passed:
124124
5. If the flush was pruned as `bool`
125125
6. If it was full flush as `bool`
126126

127+
#### Tracepoint `utxocache:add`
128+
129+
It is called when a new coin is added to the UTXO cache.
130+
131+
Arguments passed:
132+
1. Transaction ID (hash) as `pointer to unsigned chars` (i.e. 32 bytes in little-endian)
133+
2. Output index as `uint32`
134+
3. Block height the coin was added to the UTXO-set as `uint32`
135+
4. Value of the coin as `int64`
136+
5. If the coin is a coinbase as `bool`
137+
138+
#### Tracepoint `utxocache:spent`
139+
140+
It is called when a coin is spent from the UTXO cache.
141+
142+
Arguments passed:
143+
1. Transaction ID (hash) as `pointer to unsigned chars` (i.e. 32 bytes in little-endian)
144+
2. Output index as `uint32`
145+
3. Block height the coin was spent, as `uint32`
146+
4. Value of the coin as `int64`
147+
5. If the coin is a coinbase as `bool`
148+
149+
#### Tracepoint `utxocache:uncache`
150+
151+
It is called when the UTXO with the given outpoint is removed from the cache.
152+
153+
Arguments passed:
154+
1. Transaction ID (hash) as `pointer to unsigned chars` (i.e. 32 bytes in little-endian)
155+
2. Output index as `uint32`
156+
3. Block height the coin was uncached, as `uint32`
157+
4. Value of the coin as `int64`
158+
. If the coin is a coinbase as `bool`
159+
127160
## Adding tracepoints to Bitcoin Core
128161

129162
To add a new tracepoint, `#include <util/trace.h>` in the compilation unit where

src/coins.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <consensus/consensus.h>
88
#include <logging.h>
99
#include <random.h>
10+
#include <util/trace.h>
1011
#include <version.h>
1112

1213
bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
@@ -95,6 +96,12 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
9596
it->second.coin = std::move(coin);
9697
it->second.flags |= CCoinsCacheEntry::DIRTY | (fresh ? CCoinsCacheEntry::FRESH : 0);
9798
cachedCoinsUsage += it->second.coin.DynamicMemoryUsage();
99+
TRACE5(utxocache, add,
100+
outpoint.hash.data(),
101+
(uint32_t)outpoint.n,
102+
(uint32_t)coin.nHeight,
103+
(int64_t)coin.out.nValue,
104+
(bool)coin.IsCoinBase());
98105
}
99106

100107
void CCoinsViewCache::EmplaceCoinInternalDANGER(COutPoint&& outpoint, Coin&& coin) {
@@ -120,6 +127,12 @@ bool CCoinsViewCache::SpendCoin(const COutPoint &outpoint, Coin* moveout) {
120127
CCoinsMap::iterator it = FetchCoin(outpoint);
121128
if (it == cacheCoins.end()) return false;
122129
cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
130+
TRACE5(utxocache, spent,
131+
outpoint.hash.data(),
132+
(uint32_t)outpoint.n,
133+
(uint32_t)it->second.coin.nHeight,
134+
(int64_t)it->second.coin.out.nValue,
135+
(bool)it->second.coin.IsCoinBase());
123136
if (moveout) {
124137
*moveout = std::move(it->second.coin);
125138
}
@@ -231,6 +244,12 @@ void CCoinsViewCache::Uncache(const COutPoint& hash)
231244
CCoinsMap::iterator it = cacheCoins.find(hash);
232245
if (it != cacheCoins.end() && it->second.flags == 0) {
233246
cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage();
247+
TRACE5(utxocache, uncache,
248+
hash.hash.data(),
249+
(uint32_t)hash.n,
250+
(uint32_t)it->second.coin.nHeight,
251+
(int64_t)it->second.coin.out.nValue,
252+
(bool)it->second.coin.IsCoinBase());
234253
cacheCoins.erase(it);
235254
}
236255
}

src/validation.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,13 +2102,12 @@ bool CChainState::FlushStateToDisk(
21022102
full_flush_completed = true;
21032103
}
21042104
TRACE6(utxocache, flush,
2105-
(int64_t)(GetTimeMicros() - nNow.count()), // in microseconds (µs)
2106-
(u_int32_t)mode,
2107-
(u_int64_t)coins_count,
2108-
(u_int64_t)coins_mem_usage,
2109-
(bool)fFlushForPrune,
2110-
(bool)fDoFullFlush
2111-
);
2105+
(int64_t)(GetTimeMicros() - nNow.count()), // in microseconds (µs)
2106+
(u_int32_t)mode,
2107+
(u_int64_t)coins_count,
2108+
(u_int64_t)coins_mem_usage,
2109+
(bool)fFlushForPrune,
2110+
(bool)fDoFullFlush);
21122111
}
21132112
if (full_flush_completed) {
21142113
// Update best block in wallet (so we can detect restored wallets).

0 commit comments

Comments
 (0)