-
Notifications
You must be signed in to change notification settings - Fork 4.5k
General Debugging
Although it isn't the most advanced procedure, sometimes logging state to the screen is sufficient to figure out a problem. The following outlines how to add logging statements to a desired test.
-
Make sure the following line of code is at the top of your test to “route” log statements to terminal:
solana_logger::setup()
-
Add any of the following statements to display whatever information you'd like:
error!(), info!(), warn!(), debug!(), trace!()
- Note that the codebase contains these statements which will also be displayed on screen. As such, if you want to reduce "noise", it may be preferable to choose a higher level (error or info).
-
Set the
RUST_LOG
environment variable, making sure to choose a level equal to or lower than the statement in previous step.- For example:
export RUST_LOG=solana=error
- The level can also be specified for a single command:
RUST_LOG=solana=error cargo test your_test
- The level can also be specified on a per-crate basis, such as:
RUST_LOG=solana_ledger=trace,solana_core=info cargo test your_test
- For example:
Adding log statements to executables, such as solana-validator
, is similar. Same as before, make sure your executable is run with the proper log level, and consider adding any prints at a high level to avoid excessive output.
For more info, check out the official documentation: https://docs.rs/log/latest/log/index.html
Running a failing unit test inside a debugger provides much more detail, and is a useful tool to have in your tool belt. The following outlines the process for setting up and running unit tests with rust-lldb
.
- Build the code in debug mode (debug mode is the default mode for
cargo build
)- This is obvious, but worthwhile to mention. It's likely that the code has already built and the tests have been run, which prompted the reason to run the test(s) in a debugger.
- Locate the binary to debug
- The unit test binaries are in
target/debug/deps
. - Binaries have a hash appended as a string to the end of the binary's filename.
- The unit test binaries are in
- Launch
rust-lldb
$ rust-lldb target/debug/deps/solana_binary_to_debug-SOMEHASH
- Set a breakpoint
(lldb) breakpoint set -r test_name_here
- Run
(lldb) run -- test_name_here
Inspecting core dumps can be useful for examining the state of a program at the time of a crash.
System configuration may not allow the generation of core dumps by default. Perform the following steps to allow generation of core dumps:
- Check that a program is configured to handle core patterns by printing the contents of
/proc/sys/kernel/core_pattern
. For example,
$ cat /proc/sys/kernel/core_pattern
|/lib/systemd/systemd-coredump %P %u %g %s %t 9223372036854775808 %h
- Confirm that the service in step above is enabled; it might be disabled by default.
- Confirm that the limit for created core files is large enough.
$ ulimit -c
unlimited
If the above is 0
, no core files will be created.
At the time of writing this, the project is using jemalloc in place of the system allocator. jemalloc has some builtins to allow profiling; the following procedure outlines how to do so. The jemalloc wiki also has some good documentation, specifically in the "Use cases" pages.
- Clone and build the jemalloc repo by following these instructions.
- Install
ghostscript
andgraphviz
; these will be needed if you wish to create graph outputs.
$ sudo apt install ghostscript graphviz
- Note that there is a
jeprof
binary in thebin
directory.
The directions listed below will assume that solana-validator
is the binary to profile.
- Apply the following patch to enable debug information in the release binaries, as well as the jemalloc profiling feature itself.
Patch
diff --git a/Cargo.toml b/Cargo.toml
index 9aad90aeb4..f0492c7fce 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -92,5 +92,14 @@ exclude = [
"programs/bpf",
]
+[profile.release]
+debug = true
+
+[profile.release.package."*"]
+debug = true
+
+[profile.release.build-override]
+debug = true
+
# This prevents a Travis CI error when building for Windows.
resolver = "2"
diff --git a/ledger-tool/Cargo.toml b/ledger-tool/Cargo.toml
index 7a984bf6ad..28eb7ebf4f 100644
--- a/ledger-tool/Cargo.toml
+++ b/ledger-tool/Cargo.toml
@@ -39,7 +39,7 @@ solana-vote-program = { path = "../programs/vote", version = "=1.14.2" }
tokio = { version = "1", features = ["full"] }
[target.'cfg(not(target_env = "msvc"))'.dependencies]
-jemallocator = { package = "tikv-jemallocator", version = "0.4.1", features = ["unprefixed_malloc_on_supported_platforms"] }
+jemallocator = { package = "tikv-jemallocator", version = "0.4.1", features = ["profiling", "unprefixed_malloc_on_supported_platforms"] }
[dev-dependencies]
assert_cmd = "2.0"
diff --git a/validator/Cargo.toml b/validator/Cargo.toml
index 877ffccbc9..8db96cacf2 100644
--- a/validator/Cargo.toml
+++ b/validator/Cargo.toml
@@ -55,7 +55,7 @@ solana-vote-program = { path = "../programs/vote", version = "=1.14.2" }
symlink = "0.1.0"
[target.'cfg(not(target_env = "msvc"))'.dependencies]
-jemallocator = { package = "tikv-jemallocator", version = "0.4.1", features = ["unprefixed_malloc_on_supported_platforms"] }
+jemallocator = { package = "tikv-jemallocator", version = "0.4.1", features = ["profiling", "unprefixed_malloc_on_supported_platforms"] }
[target."cfg(unix)".dependencies]
libc = "0.2.126"
- With the patch applied, recompile the the desired binary with the following flags. For example, the build command may look like:
$ RUSTFLAGS='-g -C force-frame-pointers=yes' ./cargo build --release --features jemallocator/profiling
- Execute the
solana-validator
with the following flags; check out the documentation here to see what these flags do and tweak them as necessary to fit your use case.
$ MALLOC_CONF="prof:true,lg_prof_interval:32,lg_prof_sample:17,prof_prefix:jeprof" solana-validator ...
- As your process runs, it should now create files of the format
jeprof.<...>.heap
.
- Run something similar to the following command to create a PDF output; see the
jeprof
help for all the options:
$ jeprof --show_bytes /path/to/binary /path/to/heap/profile/file --pdf > heap.pdf
Note that if your process created multiple files, you can pass multiple files to jeprof
. For exampple, if all of your profile files from one run are in the same directory, you could do:
$ jeprof --show_bytes /path/to/binary /path/to/heap/profile/directory/jeprof.* --pdf > heap.pdf
- General
- Feature Gates
- Technical
- Schedule
- Testnet