diff --git a/.gitignore b/.gitignore index 91b703d57a..fdf8a75188 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,9 @@ **/*.rs.bk .idea/ .env +.gdb_history *.tsm **/.DS_Store **/.vscode -query_tests/cases/**/*.out \ No newline at end of file +query_tests/cases/**/*.out +valgrind-out.txt diff --git a/Cargo.lock b/Cargo.lock index ea7bd73ef1..4a3c18eae7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "1.0.8" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c98233c6673d8601ab23e77eb38f999c51100d46c5703b17288c57fddf3a1ffe" +checksum = "54f002ce7d0c5e809ebb02be78fd503aeed4a511fd0fcaff6e6914cbdabbfa33" dependencies = [ "bstr", "doc-comment", diff --git a/Cargo.toml b/Cargo.toml index 14e2703c8a..2b2f220f54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -142,7 +142,7 @@ parking_lot = "0.11.1" write_buffer = { path = "write_buffer" } # Crates.io dependencies, in alphabetical order -assert_cmd = "1.0.0" +assert_cmd = "2.0.0" flate2 = "1.0" hex = "0.4.2" predicates = "2.0.2" diff --git a/docs/valgrind.md b/docs/valgrind.md new file mode 100644 index 0000000000..c45ae56b26 --- /dev/null +++ b/docs/valgrind.md @@ -0,0 +1,42 @@ +# Valgrind +This document explains how to use [Valgrind] to perform certain debug tasks. + +## Build +Create a debug build that uses the system memory allocator (i.e. neither [heappy] nor [jemalloc]): + +```console +$ cargo build --no-default-features +``` + +## Memory Leaks +There is a script that does most of the config setting. Just start the server with: + +```console +$ ./scripts/valgrind_leak ./target/debug/influxdb_iox run ... +``` + +You can kill the server w/ `CTRL-C` when you're ready. The [Valgrind] output will be written to `valgrind-out.txt`. + +## Suppression Rules +[Valgrind] allows you to suppress certain outputs. This can be used to ignore known "issues" like that [lazycell] leaks. +For IOx we provide a file that is used by the scripts (under `scripts/valgrind.supp`). If you plan to write your own +rules, here are some useful links: + +- +- +- + +You may also use the `--gen-suppressions=all` to auto-generate supppression rules: + +```console +$ ./scripts/valgrind_leak --gen-suppressions=all ./target/debug/influxdb_iox run ... +``` + +Note that Rust symbols like `influxdb_iox::main` are mangled in a way that [Valgrind] cannot parse them (e.g. to +`_ZN12influxdb_iox4main17h940b8bf02831a9d8E`). The easiest way is to replace `::` w/ `*` and prepand and append an +additional wildcard `*`, so `influxdb_iox::main` gets `*influxdb_iox*main*`. + +[heappy]: https://github.com/mkmik/heappy +[jemalloc]: ttps://github.com/jemalloc/jemalloc +[lazycell]: https://crates.io/crates/lazycell +[Valgrind]: https://valgrind.org/ diff --git a/scripts/valgrind.supp b/scripts/valgrind.supp new file mode 100644 index 0000000000..ae6f2f8d80 --- /dev/null +++ b/scripts/valgrind.supp @@ -0,0 +1,31 @@ +{ + dlopen + Memcheck:Leak + ... + fun:do_dlopen + ... +} + +{ + lazystatic + Memcheck:Leak + ... + fun:__static_ref_initialize + ... +} + +{ + oncecell + Memcheck:Leak + ... + fun:*once_cell*imp*initialize_inner* + ... +} + +{ + init_logs_and_tracing + Memcheck:Leak + ... + fun:*init_logs_and_tracing* + ... +} diff --git a/scripts/valigrind_leak b/scripts/valigrind_leak new file mode 100755 index 0000000000..92f23c93c7 --- /dev/null +++ b/scripts/valigrind_leak @@ -0,0 +1,14 @@ +#!/bin/bash +set -eu -o pipefail + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +exec valgrind \ + --leak-check=full \ + --log-file=valgrind-out.txt \ + --num-callers=50 \ + --show-leak-kinds=all \ + --suppressions="$SCRIPT_DIR/valgrind.supp" \ + --track-origins=yes \ + --verbose \ + $@ diff --git a/src/influxdb_ioxd.rs b/src/influxdb_ioxd.rs index 9c3b1e31e1..ac21021139 100644 --- a/src/influxdb_ioxd.rs +++ b/src/influxdb_ioxd.rs @@ -130,18 +130,41 @@ fn make_server( app_server } +#[cfg(all(not(feature = "heappy"), not(feature = "jemalloc_replacing_malloc")))] +fn build_malloc_conf() -> String { + "system".to_string() +} + +#[cfg(all(feature = "heappy", not(feature = "jemalloc_replacing_malloc")))] +fn build_malloc_conf() -> String { + "heappy".to_string() +} + +#[cfg(all(not(feature = "heappy"), feature = "jemalloc_replacing_malloc"))] +fn build_malloc_conf() -> String { + tikv_jemalloc_ctl::config::malloc_conf::mib() + .unwrap() + .read() + .unwrap() + .to_string() +} + +#[cfg(all(feature = "heappy", feature = "jemalloc_replacing_malloc"))] +fn build_malloc_conf() -> String { + compile_error!("must use exactly one memory allocator") +} + /// This is the entry point for the IOx server. `config` represents /// command line arguments, if any. pub async fn main(config: Config) -> Result<()> { let git_hash = option_env!("GIT_HASH").unwrap_or("UNKNOWN"); let num_cpus = num_cpus::get(); - let build_malloc_conf = tikv_jemalloc_ctl::config::malloc_conf::mib() - .unwrap() - .read() - .unwrap(); + let build_malloc_conf = build_malloc_conf(); info!( git_hash, - num_cpus, build_malloc_conf, "InfluxDB IOx server starting" + num_cpus, + %build_malloc_conf, + "InfluxDB IOx server starting", ); // Install custom panic handler and forget about it. diff --git a/src/main.rs b/src/main.rs index ff6355d108..056c41bdd1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,9 +46,6 @@ static VERSION_STRING: Lazy = Lazy::new(|| { ) }); -#[cfg(not(any(feature = "heappy", feature = "jemalloc_replacing_malloc")))] -compile_error!("you need to pick either heappy or jemalloc_replacing_malloc feature, cargo can't pick a default out of a mutually exclusive set"); - #[cfg(all(feature = "heappy", feature = "jemalloc_replacing_malloc"))] compile_error!("heappy and jemalloc_replacing_malloc features are mutually exclusive");