Skip to content

Commit

Permalink
tracing: only prepare tracepoint args if attached
Browse files Browse the repository at this point in the history
Before this commit, we would prepare/calculate tracepoint arguments
regadless if the tracepoint was being used or not. While we made sure
to not include too expensive-to-calculate arguments in our tracepoints,
this commit introduces gating to make sure the arguments are only
prepared if the tracepoints are actually used. This is a win-win
improvment to our tracing framework. Users not interested in tracing
now have their overhead removed to a cheap 'greater than 0' compare.
As the semaphore-gating technique used here is availabe in bpftrace,
bcc, and libbpf, users interested in tracing don't have to change
their tracing scripts while profiting from potential future
tracepoints passing sligly more expenive-to-calculate data. One
example, in the context of [bitcoin#26531]'s mempool tracepoints could be
passing serialized transactions for RBF replacements.

TODO: This works by..

[bitcoin#26531]: bitcoin#26531
  • Loading branch information
0xB10C committed Nov 25, 2022
1 parent 2b21ff9 commit e2bc73c
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 7 deletions.
6 changes: 3 additions & 3 deletions doc/tracing.md
Expand Up @@ -314,11 +314,11 @@ Look for the notes with the description `NT_STAPSDT`.
```
$ readelf -n ./src/bitcoind | grep NT_STAPSDT -A 4 -B 2
Displaying notes found in: .note.stapsdt
Owner Data size Description
Owner Data size Description
stapsdt 0x0000005d NT_STAPSDT (SystemTap probe descriptors)
Provider: net
Name: outbound_message
Location: 0x0000000000107c05, Base: 0x0000000000579c90, Semaphore: 0x0000000000000000
Location: 0x0000000000107c05, Base: 0x0000000000579c90, Semaphore: 0x0000000000a69780
Arguments: -8@%r12 8@%rbx 8@%rdi 8@192(%rsp) 8@%rax 8@%rdx
```
Expand All @@ -337,7 +337,7 @@ between distributions. For example, on

```
$ tplist -l ./src/bitcoind -v
b'net':b'outbound_message' [sema 0x0]
b'net':b'outbound_message' [sema 0xa69780]
1 location(s)
6 argument(s)
Expand Down
4 changes: 4 additions & 0 deletions src/coins.cpp
Expand Up @@ -10,6 +10,10 @@
#include <util/trace.h>
#include <version.h>

TRACEPOINT_SEMAPHORE(utxocache, add);
TRACEPOINT_SEMAPHORE(utxocache, spent);
TRACEPOINT_SEMAPHORE(utxocache, uncache);

bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
Expand Down
3 changes: 3 additions & 0 deletions src/net.cpp
Expand Up @@ -109,6 +109,9 @@ const std::string NET_MESSAGE_TYPE_OTHER = "*other*";
static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
static const uint64_t RANDOMIZER_ID_ADDRCACHE = 0x1cf2e4ddd306dda9ULL; // SHA256("addrcache")[0:8]

TRACEPOINT_SEMAPHORE(net, outbound_message);

//
// Global state variables
//
Expand Down
2 changes: 2 additions & 0 deletions src/net_processing.cpp
Expand Up @@ -185,6 +185,8 @@ static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET{MAX_ADDR_TO_SEND};
/** The compactblocks version we support. See BIP 152. */
static constexpr uint64_t CMPCTBLOCKS_VERSION{2};

TRACEPOINT_SEMAPHORE(net, inbound_message);

// Internal stuff
namespace {
/** Blocks that are in flight, and that are in the queue to be downloaded. */
Expand Down
46 changes: 42 additions & 4 deletions src/util/trace.h
Expand Up @@ -11,16 +11,54 @@
// the optional variadic macros to define tracepoints.
#define SDT_USE_VARIADIC 1

// Setting _SDT_HAS_SEMAPHORES let's systemtap (sys/sdt.h) know that we want to
// use the optional semaphore feature for our tracepoints. This feature allows
// us to check if something is attached to a tracepoint. We only want to prepare
// some potentially expensive tracepoint arguments, if the tracepoint is being
// used. Here, an expensive argument preparation could, for example, be
// calculating a hash or serialization of a data structure.
#define _SDT_HAS_SEMAPHORES 1

#include <sys/sdt.h>

// A USDT tracepoint with zero to twelve arguments.
#define TRACEPOINT(context, event, args...) STAP_PROBEV(context, event, args)
// Used to define a counting semaphore for a tracepoint. This semaphore is
// automatically incremented by tracing frameworks (bpftrace, bcc, libbpf, ...)
// upon attaching to the tracepoint and decremented when detaching. This needs
// to be a global variable. It's placed in the '.probes' ELF section.
#define TRACEPOINT_SEMAPHORE(context, event) \
unsigned short context##_##event##_semaphore __attribute__((section (".probes")))

// Returns true if something is attached to the tracepoint.
#define TRACEPOINT_ACTIVE(context, event) context##_##event##_semaphore > 0

// A USDT tracepoint with zero to twelve arguments. Here, it **IS** checked that
// the tracepoint is active before preparing it's arguments. Use the
// TRACEPOINT_UNCHECKED macro if you want to manually check that the tracepoint
// is active.
#define TRACEPOINT(context, event, args...) \
if (TRACEPOINT_ACTIVE(context, event)) \
STAP_PROBEV(context, event, args)

// A USDT tracepoint with zero to twelve arguments. Here, it is **NOT** checked
// that the tracepoint is active before preparing it's arguments. Use this macro
// if you want to, for example, prepare expensive tracepoint arguments over
// multiple lines. Example usage:
//
// if (TRACEPOINT_ACTIVE(context, event)) {
// result = expensive_function();
// TRACEPOINT_UNCHECKED(context, event, result);
// }
//
#define TRACEPOINT_UNCHECKED(context, event, args...) \
STAP_PROBEV(context, event, args)

#else

#define TRACEPOINT_SEMAPHORE(context, event)
#define TRACEPOINT_ACTIVE(context, event)
#define TRACEPOINT(context, event, args...)
#define TRACEPOINT_UNCHECKED(context, event, args...)

#endif

#endif // ENABLE_TRACING

#endif // BITCOIN_UTIL_TRACE_H
3 changes: 3 additions & 0 deletions src/validation.cpp
Expand Up @@ -122,6 +122,9 @@ GlobalMutex g_best_block_mutex;
std::condition_variable g_best_block_cv;
uint256 g_best_block;

TRACEPOINT_SEMAPHORE(validation, block_connected);
TRACEPOINT_SEMAPHORE(utxocache, flush);

const CBlockIndex* Chainstate::FindForkInGlobalIndex(const CBlockLocator& locator) const
{
AssertLockHeld(cs_main);
Expand Down
5 changes: 5 additions & 0 deletions src/wallet/spend.cpp
Expand Up @@ -24,6 +24,11 @@

using interfaces::FoundBlock;

TRACEPOINT_SEMAPHORE(coin_selection, selected_coins);
TRACEPOINT_SEMAPHORE(coin_selection, normal_create_tx_internal);
TRACEPOINT_SEMAPHORE(coin_selection, attempting_aps_create_tx);
TRACEPOINT_SEMAPHORE(coin_selection, aps_create_tx_internal);

namespace wallet {
static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES{100};

Expand Down

0 comments on commit e2bc73c

Please sign in to comment.