perf(logging): strip debug log messages at compile-time#4365
Conversation
|
We're still incurring the cost of calculating arguments (if they are not Lazy), correct? Have you done any benchmarks? Curious about the results 🦊 |
|
Is doing this at compile time best? feels hard to get operators to re-compile, vs having a global variable being set to off based on reading the config If its at compile time, were anyways doing something global |
I will add more insights about this today before merging. |
|
@melekes and @ValarDragon, to clarify the solution, it leverages a Go feature that removes dead code at compile time. Essentially, this strips out any Debug instructions from the final binary, ensuring zero allocations since these instructions don’t exist in the compiled output. For example, here's the Note that it is on If you compile a binary with the I recognize that, from an operator's perspective, re-compiling a binary may not initially seem ideal. However, this approach is the safest and most effective way to eliminate any risk of extra allocations from debug messages, ultimately boosting performance for operators. Given these benefits, I believe re-compilation will be a reasonable step for them. Alternatively, we could explore a solution based on conditional statements (if checks), though this would involve a significant refactor and still might not fully eliminate allocations. If needed, I can add additional tests to validate these outcomes and ensure reliability. Might be a good idea to add benchmarks too. |
|
compile time is the way 👍 |
|
The question for me now is whether the official binaries should have debug level enabled or not. I agree with @ValarDragon that changing the executed binary when we want to debug something is not really the best way to go. At the same time, this is another (apparently very efficient) option to reduce the cost of debug log calls, when debugging is disabled. |
|
We agreed this is a good use case for operators looking for optimal performance. However, there might be alternatives that would require more refactoring but would allow a granular and configurable approach to the problem. I will merge this and say it partially closes the issue. In the future, I can submit another PR that implements the other approach, too, so this way, we will cater to multiple operators. |
partially close: #2847 Logging debug messages can lead to significant memory allocations, especially when outputting variable values. In Go, even if log_level is not set to debug, these allocations can still occur because the program evaluates the debug statements regardless of the log level. To prevent unnecessary memory usage, you can strip out all debug-level code from the binary at compile time using build flags. This approach improves the performance of CometBFT by excluding debug messages entirely, even when `log_level` is set to `debug`. This technique is ideal for production environments that prioritize performance optimization over debug logging. > Note: Compiling CometBFT with this method will completely disable all debug messages. If you require debug output, avoid compiling the binary with these settings. In order to build a binary stripping all debug log messages (e.g. `log.Debug()`) from the binary, use the `nodebug` tag: ``` COMETBFT_BUILD_OPTIONS=nodebug make install ``` once it's installed you can run a `kvstore` example with `log_level = "debug"` set in the `config.toml` and you will see that no debug messages are shown in the log. cc: @ValarDragon #### PR checklist - [ ] ~~Tests written/updated~~ - [X] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [X] Updated relevant documentation (`docs/` or `spec/`) and code comments --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 51e9948)
…) (#4375) partially close: #2847 Logging debug messages can lead to significant memory allocations, especially when outputting variable values. In Go, even if log_level is not set to debug, these allocations can still occur because the program evaluates the debug statements regardless of the log level. To prevent unnecessary memory usage, you can strip out all debug-level code from the binary at compile time using build flags. This approach improves the performance of CometBFT by excluding debug messages entirely, even when `log_level` is set to `debug`. This technique is ideal for production environments that prioritize performance optimization over debug logging. > Note: Compiling CometBFT with this method will completely disable all debug messages. If you require debug output, avoid compiling the binary with these settings. In order to build a binary stripping all debug log messages (e.g. `log.Debug()`) from the binary, use the `nodebug` tag: ``` COMETBFT_BUILD_OPTIONS=nodebug make install ``` once it's installed you can run a `kvstore` example with `log_level = "debug"` set in the `config.toml` and you will see that no debug messages are shown in the log. cc: @ValarDragon #### PR checklist - [ ] ~~Tests written/updated~~ - [X] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [X] Updated relevant documentation (`docs/` or `spec/`) and code comments <hr>This is an automatic backport of pull request #4365 done by [Mergify](https://mergify.com). Co-authored-by: Andy Nogueira <me@andynogueira.dev>
partially close: #2847 Logging debug messages can lead to significant memory allocations, especially when outputting variable values. In Go, even if log_level is not set to debug, these allocations can still occur because the program evaluates the debug statements regardless of the log level. To prevent unnecessary memory usage, you can strip out all debug-level code from the binary at compile time using build flags. This approach improves the performance of CometBFT by excluding debug messages entirely, even when `log_level` is set to `debug`. This technique is ideal for production environments that prioritize performance optimization over debug logging. > Note: Compiling CometBFT with this method will completely disable all debug messages. If you require debug output, avoid compiling the binary with these settings. In order to build a binary stripping all debug log messages (e.g. `log.Debug()`) from the binary, use the `nodebug` tag: ``` COMETBFT_BUILD_OPTIONS=nodebug make install ``` once it's installed you can run a `kvstore` example with `log_level = "debug"` set in the `config.toml` and you will see that no debug messages are shown in the log. cc: @ValarDragon - [ ] ~~Tests written/updated~~ - [X] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [X] Updated relevant documentation (`docs/` or `spec/`) and code comments --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
partially close: #2847 Logging debug messages can lead to significant memory allocations, especially when outputting variable values. In Go, even if log_level is not set to debug, these allocations can still occur because the program evaluates the debug statements regardless of the log level. To prevent unnecessary memory usage, you can strip out all debug-level code from the binary at compile time using build flags. This approach improves the performance of CometBFT by excluding debug messages entirely, even when `log_level` is set to `debug`. This technique is ideal for production environments that prioritize performance optimization over debug logging. > Note: Compiling CometBFT with this method will completely disable all debug messages. If you require debug output, avoid compiling the binary with these settings. In order to build a binary stripping all debug log messages (e.g. `log.Debug()`) from the binary, use the `nodebug` tag: ``` COMETBFT_BUILD_OPTIONS=nodebug make install ``` once it's installed you can run a `kvstore` example with `log_level = "debug"` set in the `config.toml` and you will see that no debug messages are shown in the log. cc: @ValarDragon - [ ] ~~Tests written/updated~~ - [X] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [X] Updated relevant documentation (`docs/` or `spec/`) and code comments --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
partially close: #2847 Logging debug messages can lead to significant memory allocations, especially when outputting variable values. In Go, even if log_level is not set to debug, these allocations can still occur because the program evaluates the debug statements regardless of the log level. To prevent unnecessary memory usage, you can strip out all debug-level code from the binary at compile time using build flags. This approach improves the performance of CometBFT by excluding debug messages entirely, even when `log_level` is set to `debug`. This technique is ideal for production environments that prioritize performance optimization over debug logging. > Note: Compiling CometBFT with this method will completely disable all debug messages. If you require debug output, avoid compiling the binary with these settings. In order to build a binary stripping all debug log messages (e.g. `log.Debug()`) from the binary, use the `nodebug` tag: ``` COMETBFT_BUILD_OPTIONS=nodebug make install ``` once it's installed you can run a `kvstore` example with `log_level = "debug"` set in the `config.toml` and you will see that no debug messages are shown in the log. cc: @ValarDragon - [ ] ~~Tests written/updated~~ - [X] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [X] Updated relevant documentation (`docs/` or `spec/`) and code comments --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
partially close: #2847 Logging debug messages can lead to significant memory allocations, especially when outputting variable values. In Go, even if log_level is not set to debug, these allocations can still occur because the program evaluates the debug statements regardless of the log level. To prevent unnecessary memory usage, you can strip out all debug-level code from the binary at compile time using build flags. This approach improves the performance of CometBFT by excluding debug messages entirely, even when `log_level` is set to `debug`. This technique is ideal for production environments that prioritize performance optimization over debug logging. > Note: Compiling CometBFT with this method will completely disable all debug messages. If you require debug output, avoid compiling the binary with these settings. In order to build a binary stripping all debug log messages (e.g. `log.Debug()`) from the binary, use the `nodebug` tag: ``` COMETBFT_BUILD_OPTIONS=nodebug make install ``` once it's installed you can run a `kvstore` example with `log_level = "debug"` set in the `config.toml` and you will see that no debug messages are shown in the log. cc: @ValarDragon - [ ] ~~Tests written/updated~~ - [X] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [X] Updated relevant documentation (`docs/` or `spec/`) and code comments --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
partially close: #2847 Logging debug messages can lead to significant memory allocations, especially when outputting variable values. In Go, even if log_level is not set to debug, these allocations can still occur because the program evaluates the debug statements regardless of the log level. To prevent unnecessary memory usage, you can strip out all debug-level code from the binary at compile time using build flags. This approach improves the performance of CometBFT by excluding debug messages entirely, even when `log_level` is set to `debug`. This technique is ideal for production environments that prioritize performance optimization over debug logging. > Note: Compiling CometBFT with this method will completely disable all debug messages. If you require debug output, avoid compiling the binary with these settings. In order to build a binary stripping all debug log messages (e.g. `log.Debug()`) from the binary, use the `nodebug` tag: ``` COMETBFT_BUILD_OPTIONS=nodebug make install ``` once it's installed you can run a `kvstore` example with `log_level = "debug"` set in the `config.toml` and you will see that no debug messages are shown in the log. cc: @ValarDragon - [ ] ~~Tests written/updated~~ - [X] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [X] Updated relevant documentation (`docs/` or `spec/`) and code comments --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

partially close: #2847
Logging debug messages can lead to significant memory allocations, especially when outputting variable values. In Go, even if log_level is not set to debug, these allocations can still occur because the program evaluates the debug statements regardless of the log level.
To prevent unnecessary memory usage, you can strip out all debug-level code from the binary at compile time using build flags. This approach improves the performance of CometBFT by excluding debug messages entirely, even when
log_levelis set todebug. This technique is ideal for production environments that prioritize performance optimization over debug logging.In order to build a binary stripping all debug log messages (e.g.
log.Debug()) from the binary, use thenodebugtag:once it's installed you can run a
kvstoreexample withlog_level = "debug"set in theconfig.tomland you will see that no debug messages are shown in the log.cc: @ValarDragon
PR checklist
Tests written/updated.changelog(we use unclog to manage our changelog)docs/orspec/) and code comments