From 9604046bb24a83d7f7b3a2b2694ffbc6d7e33081 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Thu, 2 Jul 2026 10:55:57 -0500 Subject: [PATCH 1/4] Store jsonbin sidecar paths relative to JSON output Keep --jsonbin sidecar files written next to the JSON output file, but record their filenames relative to the JSON file directory. This makes generated JSON and its sidecar directories relocatable as a unit and avoids embedding the benchmark process working-directory relationship into the JSON payload. Add a focused json_printer test that verifies sample-time and sample-frequency sidecars are written beside the JSON file while summary filename fields contain JSON-relative paths. --- nvbench/json_printer.cu | 128 +++++++++++++++++++++++++++------------- testing/CMakeLists.txt | 1 + testing/json_printer.cu | 104 ++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 42 deletions(-) create mode 100644 testing/json_printer.cu diff --git a/nvbench/json_printer.cu b/nvbench/json_printer.cu index 1c994455..9178e97a 100644 --- a/nvbench/json_printer.cu +++ b/nvbench/json_printer.cu @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -115,6 +116,57 @@ void write_named_values(JsonNode &node, const nvbench::named_values &values) // see: https://github.com/NVIDIA/nvbench/issues/255 static constexpr std::size_t preferred_buffer_nbytes = 4096; +struct jsonbin_directory_paths +{ + fs::path write_path; + fs::path summary_path; +}; + +jsonbin_directory_paths make_jsonbin_directory_paths(const std::string &stream_name, + const std::string &suffix) +{ + const fs::path stream_path{stream_name}; + const fs::path sidecar_dir{stream_path.filename().string() + suffix}; + const auto stream_parent = stream_path.parent_path(); + return {stream_parent.empty() ? sidecar_dir : stream_parent / sidecar_dir, sidecar_dir}; +} + +void ensure_output_directory(const fs::path &dir) +{ + std::error_code create_ec; + fs::create_directories(dir, create_ec); + + std::error_code status_ec; + if (fs::is_directory(dir, status_ec)) + { + return; + } + + std::error_code exists_ec; + if (fs::exists(dir, exists_ec)) + { + NVBENCH_THROW(std::runtime_error, "'{}' exists and is not a directory.", dir.string()); + } + + if (create_ec) + { + NVBENCH_THROW(std::runtime_error, + "Failed to create result directory '{}': {}.", + dir.string(), + create_ec.message()); + } + + if (status_ec) + { + NVBENCH_THROW(std::runtime_error, + "Failed to inspect result directory '{}': {}.", + dir.string(), + status_ec.message()); + } + + NVBENCH_THROW(std::runtime_error, "Failed to create result directory '{}'.", dir.string()); +} + template void swap_bytes_impl(char *p, std::index_sequence) { @@ -225,27 +277,19 @@ void json_printer::do_process_bulk_data_float64(state &state, nvbench::cpu_timer timer; timer.start(); - fs::path result_path{m_stream_name + "-bin/"}; + auto paths = make_jsonbin_directory_paths(m_stream_name, "-bin"); try { - if (!fs::exists(result_path)) - { - if (!fs::create_directory(result_path)) - { - NVBENCH_THROW(std::runtime_error, "{}", "Failed to create result directory '{}'."); - } - } - else if (!fs::is_directory(result_path)) - { - NVBENCH_THROW(std::runtime_error, "{}", "'{}' exists and is not a directory."); - } + ensure_output_directory(paths.write_path); const auto file_id = m_num_jsonbin_files++; - result_path /= fmt::format("{:d}.bin", file_id); + const fs::path filename{fmt::format("{:d}.bin", file_id)}; + paths.write_path /= filename; + paths.summary_path /= filename; std::ofstream out; out.exceptions(out.exceptions() | std::ios::failbit | std::ios::badbit); - out.open(result_path, std::ios::binary | std::ios::out); + out.open(paths.write_path, std::ios::binary | std::ios::out); write_out_values_as_float32(out, data); } @@ -254,9 +298,12 @@ void json_printer::do_process_bulk_data_float64(state &state, if (auto printer_ptr = state.get_benchmark().get_printer()) { auto &printer = *printer_ptr; - printer.log( - nvbench::log_level::warn, - fmt::format("Error writing {} ({}) to {}: {}", tag, hint, result_path.string(), e.what())); + printer.log(nvbench::log_level::warn, + fmt::format("Error writing {} ({}) to {}: {}", + tag, + hint, + paths.write_path.string(), + e.what())); } } // end catch @@ -266,7 +313,7 @@ void json_printer::do_process_bulk_data_float64(state &state, summ.set_string("description", "Binary file containing sample times as little-endian " "float32."); - summ.set_string("filename", result_path.string()); + summ.set_string("filename", paths.summary_path.string()); summ.set_int64("size", static_cast(data.size())); summ.set_string("hide", "Not needed in table."); @@ -274,9 +321,10 @@ void json_printer::do_process_bulk_data_float64(state &state, if (auto printer_ptr = state.get_benchmark().get_printer()) { auto &printer = *printer_ptr; - printer.log( - nvbench::log_level::info, - fmt::format("Wrote '{}' in {:>6.3f}ms", result_path.string(), timer.get_duration() * 1000)); + printer.log(nvbench::log_level::info, + fmt::format("Wrote '{}' in {:>6.3f}ms", + paths.write_path.string(), + timer.get_duration() * 1000)); } } // end hint == sample_times @@ -285,27 +333,19 @@ void json_printer::do_process_bulk_data_float64(state &state, nvbench::cpu_timer timer; timer.start(); - fs::path result_path{m_stream_name + "-freqs-bin/"}; + auto paths = make_jsonbin_directory_paths(m_stream_name, "-freqs-bin"); try { - if (!fs::exists(result_path)) - { - if (!fs::create_directory(result_path)) - { - NVBENCH_THROW(std::runtime_error, "{}", "Failed to create result directory '{}'."); - } - } - else if (!fs::is_directory(result_path)) - { - NVBENCH_THROW(std::runtime_error, "{}", "'{}' exists and is not a directory."); - } + ensure_output_directory(paths.write_path); const auto file_id = m_num_jsonbin_freq_files++; - result_path /= fmt::format("{:d}.bin", file_id); + const fs::path filename{fmt::format("{:d}.bin", file_id)}; + paths.write_path /= filename; + paths.summary_path /= filename; std::ofstream out; out.exceptions(out.exceptions() | std::ios::failbit | std::ios::badbit); - out.open(result_path, std::ios::binary | std::ios::out); + out.open(paths.write_path, std::ios::binary | std::ios::out); write_out_values_as_float32(out, data); } @@ -314,9 +354,12 @@ void json_printer::do_process_bulk_data_float64(state &state, if (auto printer_ptr = state.get_benchmark().get_printer()) { auto &printer = *printer_ptr; - printer.log( - nvbench::log_level::warn, - fmt::format("Error writing {} ({}) to {}: {}", tag, hint, result_path.string(), e.what())); + printer.log(nvbench::log_level::warn, + fmt::format("Error writing {} ({}) to {}: {}", + tag, + hint, + paths.write_path.string(), + e.what())); } } // end catch @@ -326,7 +369,7 @@ void json_printer::do_process_bulk_data_float64(state &state, summ.set_string("description", "Binary file containing sample frequencies as little-endian " "float32."); - summ.set_string("filename", result_path.string()); + summ.set_string("filename", paths.summary_path.string()); summ.set_int64("size", static_cast(data.size())); summ.set_string("hide", "Not needed in table."); @@ -334,9 +377,10 @@ void json_printer::do_process_bulk_data_float64(state &state, if (auto printer_ptr = state.get_benchmark().get_printer()) { auto &printer = *printer_ptr; - printer.log( - nvbench::log_level::info, - fmt::format("Wrote '{}' in {:>6.3f}ms", result_path.string(), timer.get_duration() * 1000)); + printer.log(nvbench::log_level::info, + fmt::format("Wrote '{}' in {:>6.3f}ms", + paths.write_path.string(), + timer.get_duration() * 1000)); } } // end hint == sample_freqs } diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index b390edf1..79f59ddf 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -16,6 +16,7 @@ set(test_srcs exception_safety.cu float64_axis.cu int64_axis.cu + json_printer.cu measure_timeout_warnings.cu named_values.cu option_parser.cu diff --git a/testing/json_printer.cu b/testing/json_printer.cu new file mode 100644 index 00000000..2360981a --- /dev/null +++ b/testing/json_printer.cu @@ -0,0 +1,104 @@ +/* + * Copyright 2026 NVIDIA Corporation + * + * Licensed under the Apache License, Version 2.0 with the LLVM exception + * (the "License"); you may not use this file except in compliance with + * the License. + * + * You may obtain a copy of the License at + * + * http://llvm.org/foundation/relicensing/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "test_asserts.cuh" + +#if __has_include() +#include +namespace fs = std::filesystem; +#elif __has_include() +#include +namespace fs = std::experimental::filesystem; +#else +#error "No or found." +#endif + +void dummy_generator(nvbench::state &) {} +NVBENCH_DEFINE_CALLABLE(dummy_generator, dummy_callable); +using dummy_bench = nvbench::benchmark; + +struct temp_directory +{ + temp_directory() + : path{fs::temp_directory_path() / + ("nvbench-json-printer-test-" + + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()))} + { + fs::create_directories(path); + } + + ~temp_directory() + { + std::error_code ec; + fs::remove_all(path, ec); + } + + fs::path path; +}; + +namespace nvbench::detail +{ +// nvbench::state construction is private to the state generator and this test +// hook; use the friend type to build a minimal state for printer testing. +struct state_tester : public nvbench::state +{ + state_tester(const nvbench::benchmark_base &bench) + : nvbench::state{bench} + {} +}; +} // namespace nvbench::detail + +void test_jsonbin_filenames_are_json_relative() +{ + const temp_directory tmp_dir; + const auto json_path = tmp_dir.path / "result.json"; + + std::ofstream json_stream{json_path}; + nvbench::json_printer printer{json_stream, json_path.string(), true}; + + dummy_bench bench; + nvbench::detail::state_tester state{bench}; + + printer.process_bulk_data(state, "nv/cold/sample_times", "sample_times", {1.0, 2.0}); + printer.process_bulk_data(state, "nv/cold/sample_freqs", "sample_freqs", {3.0, 4.0}); + + const auto samples_filename = + state.get_summary("nv/json/bin:nv/cold/sample_times").get_string("filename"); + const auto freqs_filename = + state.get_summary("nv/json/freqs-bin:nv/cold/sample_freqs").get_string("filename"); + + ASSERT(fs::path{samples_filename} == fs::path{"result.json-bin"} / "0.bin"); + ASSERT(fs::path{freqs_filename} == fs::path{"result.json-freqs-bin"} / "0.bin"); + ASSERT(fs::exists(tmp_dir.path / samples_filename)); + ASSERT(fs::exists(tmp_dir.path / freqs_filename)); +} + +int main() { test_jsonbin_filenames_are_json_relative(); } From fa6a92e7e09f2a6744c69dc93707e31f08b73ce4 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:58:07 -0500 Subject: [PATCH 2/4] Factor out jsonbin sidecar writing helper Extract the duplicated sample-times and sample-frequencies jsonbin sidecar write paths into a shared helper. This keeps directory creation, file writing, warning logging, summary metadata, and write-duration logging in one place for both sidecar types. --- nvbench/json_printer.cu | 229 ++++++++++++++++++++-------------------- 1 file changed, 113 insertions(+), 116 deletions(-) diff --git a/nvbench/json_printer.cu b/nvbench/json_printer.cu index 9178e97a..dfd59a65 100644 --- a/nvbench/json_printer.cu +++ b/nvbench/json_printer.cu @@ -118,10 +118,21 @@ static constexpr std::size_t preferred_buffer_nbytes = 4096; struct jsonbin_directory_paths { + // Files are written next to the JSON output, but summaries record paths + // relative to the JSON file's directory so the output remains relocatable. fs::path write_path; fs::path summary_path; }; +struct jsonbin_sidecar_metadata +{ + const char *directory_suffix; + const char *summary_tag_prefix; + const char *summary_name; + const char *summary_hint; + const char *summary_description; +}; + jsonbin_directory_paths make_jsonbin_directory_paths(const std::string &stream_name, const std::string &suffix) { @@ -137,13 +148,19 @@ void ensure_output_directory(const fs::path &dir) fs::create_directories(dir, create_ec); std::error_code status_ec; - if (fs::is_directory(dir, status_ec)) + const auto status = fs::status(dir, status_ec); + if (status_ec) + { + NVBENCH_THROW(std::runtime_error, + "Failed to inspect result directory '{}': {}.", + dir.string(), + status_ec.message()); + } + if (fs::is_directory(status)) { return; } - - std::error_code exists_ec; - if (fs::exists(dir, exists_ec)) + if (fs::exists(status)) { NVBENCH_THROW(std::runtime_error, "'{}' exists and is not a directory.", dir.string()); } @@ -156,14 +173,6 @@ void ensure_output_directory(const fs::path &dir) create_ec.message()); } - if (status_ec) - { - NVBENCH_THROW(std::runtime_error, - "Failed to inspect result directory '{}': {}.", - dir.string(), - status_ec.message()); - } - NVBENCH_THROW(std::runtime_error, "Failed to create result directory '{}'.", dir.string()); } @@ -238,6 +247,82 @@ void write_out_values_as_float64(std::ofstream &out, const std::vector(out, data); } +void write_jsonbin_sidecar(nvbench::state &state, + const std::string &stream_name, + std::size_t &file_count, + const std::string &tag, + const std::string &hint, + const std::vector &data, + const jsonbin_sidecar_metadata &metadata) +{ + nvbench::cpu_timer timer; + timer.start(); + + auto paths = make_jsonbin_directory_paths(stream_name, metadata.directory_suffix); + const auto file_id = file_count++; + const fs::path filename{fmt::format("{:d}.bin", file_id)}; + paths.write_path /= filename; + paths.summary_path /= filename; + + bool write_succeeded = false; + try + { + ensure_output_directory(paths.write_path.parent_path()); + + std::ofstream out; + out.exceptions(out.exceptions() | std::ios::failbit | std::ios::badbit); + out.open(paths.write_path, std::ios::binary | std::ios::out); + + write_out_values_as_float32(out, data); + out.close(); + write_succeeded = true; + } + catch (std::exception &e) + { + { + // Best-effort cleanup of any partial output. Preserve the original + // write failure as the diagnostic if removal also fails. + std::error_code remove_ec; + fs::remove(paths.write_path, remove_ec); + } + + if (auto printer_ptr = state.get_benchmark().get_printer()) + { + auto &printer = *printer_ptr; + printer.log(nvbench::log_level::warn, + fmt::format("Error writing {} ({}) to {}: {}", + tag, + hint, + paths.write_path.string(), + e.what())); + } + } // end catch + + auto &summ = state.add_summary(fmt::format("{}:{}", metadata.summary_tag_prefix, tag)); + summ.set_string("name", metadata.summary_name); + summ.set_string("hint", metadata.summary_hint); + summ.set_string("description", metadata.summary_description); + if (write_succeeded) + { + summ.set_string("filename", paths.summary_path.string()); + summ.set_int64("size", static_cast(data.size())); + } + summ.set_string("hide", "Not needed in table."); + + timer.stop(); + if (write_succeeded) + { + if (auto printer_ptr = state.get_benchmark().get_printer()) + { + auto &printer = *printer_ptr; + printer.log(nvbench::log_level::info, + fmt::format("Wrote '{}' in {:>6.3f}ms", + paths.write_path.string(), + timer.get_duration() * 1000)); + } + } +} + } // end namespace namespace nvbench @@ -274,114 +359,26 @@ void json_printer::do_process_bulk_data_float64(state &state, if (hint == "sample_times") { - nvbench::cpu_timer timer; - timer.start(); - - auto paths = make_jsonbin_directory_paths(m_stream_name, "-bin"); - try - { - ensure_output_directory(paths.write_path); - - const auto file_id = m_num_jsonbin_files++; - const fs::path filename{fmt::format("{:d}.bin", file_id)}; - paths.write_path /= filename; - paths.summary_path /= filename; - - std::ofstream out; - out.exceptions(out.exceptions() | std::ios::failbit | std::ios::badbit); - out.open(paths.write_path, std::ios::binary | std::ios::out); - - write_out_values_as_float32(out, data); - } - catch (std::exception &e) - { - if (auto printer_ptr = state.get_benchmark().get_printer()) - { - auto &printer = *printer_ptr; - printer.log(nvbench::log_level::warn, - fmt::format("Error writing {} ({}) to {}: {}", - tag, - hint, - paths.write_path.string(), - e.what())); - } - } // end catch - - auto &summ = state.add_summary(fmt::format("nv/json/bin:{}", tag)); - summ.set_string("name", "Samples Times File"); - summ.set_string("hint", "file/sample_times"); - summ.set_string("description", - "Binary file containing sample times as little-endian " - "float32."); - summ.set_string("filename", paths.summary_path.string()); - summ.set_int64("size", static_cast(data.size())); - summ.set_string("hide", "Not needed in table."); - - timer.stop(); - if (auto printer_ptr = state.get_benchmark().get_printer()) - { - auto &printer = *printer_ptr; - printer.log(nvbench::log_level::info, - fmt::format("Wrote '{}' in {:>6.3f}ms", - paths.write_path.string(), - timer.get_duration() * 1000)); - } + constexpr jsonbin_sidecar_metadata metadata{"-bin", + "nv/json/bin", + "Samples Times File", + "file/sample_times", + "Binary file containing sample times as " + "little-endian float32."}; + + write_jsonbin_sidecar(state, m_stream_name, m_num_jsonbin_files, tag, hint, data, metadata); } // end hint == sample_times if (hint == "sample_freqs") { - nvbench::cpu_timer timer; - timer.start(); - - auto paths = make_jsonbin_directory_paths(m_stream_name, "-freqs-bin"); - try - { - ensure_output_directory(paths.write_path); - - const auto file_id = m_num_jsonbin_freq_files++; - const fs::path filename{fmt::format("{:d}.bin", file_id)}; - paths.write_path /= filename; - paths.summary_path /= filename; - - std::ofstream out; - out.exceptions(out.exceptions() | std::ios::failbit | std::ios::badbit); - out.open(paths.write_path, std::ios::binary | std::ios::out); - - write_out_values_as_float32(out, data); - } - catch (std::exception &e) - { - if (auto printer_ptr = state.get_benchmark().get_printer()) - { - auto &printer = *printer_ptr; - printer.log(nvbench::log_level::warn, - fmt::format("Error writing {} ({}) to {}: {}", - tag, - hint, - paths.write_path.string(), - e.what())); - } - } // end catch - - auto &summ = state.add_summary(fmt::format("nv/json/freqs-bin:{}", tag)); - summ.set_string("name", "Samples Frequencies File"); - summ.set_string("hint", "file/sample_freqs"); - summ.set_string("description", - "Binary file containing sample frequencies as little-endian " - "float32."); - summ.set_string("filename", paths.summary_path.string()); - summ.set_int64("size", static_cast(data.size())); - summ.set_string("hide", "Not needed in table."); - - timer.stop(); - if (auto printer_ptr = state.get_benchmark().get_printer()) - { - auto &printer = *printer_ptr; - printer.log(nvbench::log_level::info, - fmt::format("Wrote '{}' in {:>6.3f}ms", - paths.write_path.string(), - timer.get_duration() * 1000)); - } + constexpr jsonbin_sidecar_metadata metadata{"-freqs-bin", + "nv/json/freqs-bin", + "Samples Frequencies File", + "file/sample_freqs", + "Binary file containing sample frequencies as " + "little-endian float32."}; + + write_jsonbin_sidecar(state, m_stream_name, m_num_jsonbin_freq_files, tag, hint, data, metadata); } // end hint == sample_freqs } From bbd859ed6f392e6e83d9d93e7715aef7bae3b7c4 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Thu, 2 Jul 2026 13:37:11 -0500 Subject: [PATCH 3/4] Test jsonbin sidecar write failure handling Cover the case where the expected sidecar directory path collides with a regular file. Verify that json_printer keeps descriptive summary metadata but omits filename and size when the sidecar file was not written. Register printer and verify output. --- testing/json_printer.cu | 60 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/testing/json_printer.cu b/testing/json_printer.cu index 2360981a..8507fd08 100644 --- a/testing/json_printer.cu +++ b/testing/json_printer.cu @@ -19,14 +19,17 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include +#include #include #include "test_asserts.cuh" @@ -45,6 +48,21 @@ void dummy_generator(nvbench::state &) {} NVBENCH_DEFINE_CALLABLE(dummy_generator, dummy_callable); using dummy_bench = nvbench::benchmark; +struct recording_printer : nvbench::printer_base +{ + explicit recording_printer(std::ostream &stream) + : nvbench::printer_base{stream} + {} + + std::vector> logs; + +protected: + void do_log(nvbench::log_level level, const std::string &msg) override + { + logs.emplace_back(level, msg); + } +}; + struct temp_directory { temp_directory() @@ -101,4 +119,44 @@ void test_jsonbin_filenames_are_json_relative() ASSERT(fs::exists(tmp_dir.path / freqs_filename)); } -int main() { test_jsonbin_filenames_are_json_relative(); } +void test_jsonbin_write_failure_omits_file_metadata() +{ + const temp_directory tmp_dir; + const auto json_path = tmp_dir.path / "result.json"; + const auto collision_path = tmp_dir.path / "result.json-bin"; + + { + std::ofstream collision{collision_path}; + collision << "not a directory"; + } + + std::ofstream json_stream{json_path}; + nvbench::json_printer printer{json_stream, json_path.string(), true}; + + std::ostringstream log_stream; + recording_printer log_printer{log_stream}; + + dummy_bench bench; + bench.set_printer(log_printer); + nvbench::detail::state_tester state{bench}; + + printer.process_bulk_data(state, "nv/cold/sample_times", "sample_times", {1.0, 2.0}); + + const auto &summary = state.get_summary("nv/json/bin:nv/cold/sample_times"); + ASSERT(summary.has_value("name")); + ASSERT(summary.has_value("hint")); + ASSERT(summary.has_value("description")); + ASSERT(!summary.has_value("filename")); + ASSERT(!summary.has_value("size")); + ASSERT(fs::is_regular_file(collision_path)); + ASSERT(log_printer.logs.size() == 1); + ASSERT(log_printer.logs[0].first == nvbench::log_level::warn); + ASSERT(log_printer.logs[0].second.find("Error writing nv/cold/sample_times (sample_times)") != + std::string::npos); +} + +int main() +{ + test_jsonbin_filenames_are_json_relative(); + test_jsonbin_write_failure_omits_file_metadata(); +} From 93e55124190fda98b024fa48d8cc2f0f308f51e8 Mon Sep 17 00:00:00 2001 From: Oleksandr Pavlyk <21087696+oleksandr-pavlyk@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:01:13 -0500 Subject: [PATCH 4/4] Clean up jsonbin sidecar logging Factor repeated optional benchmark-printer logging in write_jsonbin_sidecar into a local helper used by both warning and success paths. Also tidy the jsonbin summary names for sample time and frequency sidecar files. --- nvbench/json_printer.cu | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/nvbench/json_printer.cu b/nvbench/json_printer.cu index dfd59a65..9871eaed 100644 --- a/nvbench/json_printer.cu +++ b/nvbench/json_printer.cu @@ -265,6 +265,13 @@ void write_jsonbin_sidecar(nvbench::state &state, paths.summary_path /= filename; bool write_succeeded = false; + auto log_if_present = [&state](nvbench::log_level level, const std::string &msg) { + if (auto printer_ptr = state.get_benchmark().get_printer()) + { + printer_ptr->log(level, msg); + } + }; + try { ensure_output_directory(paths.write_path.parent_path()); @@ -286,16 +293,12 @@ void write_jsonbin_sidecar(nvbench::state &state, fs::remove(paths.write_path, remove_ec); } - if (auto printer_ptr = state.get_benchmark().get_printer()) - { - auto &printer = *printer_ptr; - printer.log(nvbench::log_level::warn, - fmt::format("Error writing {} ({}) to {}: {}", - tag, - hint, - paths.write_path.string(), - e.what())); - } + log_if_present(nvbench::log_level::warn, + fmt::format("Error writing {} ({}) to {}: {}", + tag, + hint, + paths.write_path.string(), + e.what())); } // end catch auto &summ = state.add_summary(fmt::format("{}:{}", metadata.summary_tag_prefix, tag)); @@ -312,14 +315,10 @@ void write_jsonbin_sidecar(nvbench::state &state, timer.stop(); if (write_succeeded) { - if (auto printer_ptr = state.get_benchmark().get_printer()) - { - auto &printer = *printer_ptr; - printer.log(nvbench::log_level::info, - fmt::format("Wrote '{}' in {:>6.3f}ms", - paths.write_path.string(), - timer.get_duration() * 1000)); - } + log_if_present(nvbench::log_level::info, + fmt::format("Wrote '{}' in {:>6.3f}ms", + paths.write_path.string(), + timer.get_duration() * 1000)); } } @@ -361,7 +360,7 @@ void json_printer::do_process_bulk_data_float64(state &state, { constexpr jsonbin_sidecar_metadata metadata{"-bin", "nv/json/bin", - "Samples Times File", + "Sample Times File", "file/sample_times", "Binary file containing sample times as " "little-endian float32."}; @@ -373,7 +372,7 @@ void json_printer::do_process_bulk_data_float64(state &state, { constexpr jsonbin_sidecar_metadata metadata{"-freqs-bin", "nv/json/freqs-bin", - "Samples Frequencies File", + "Sample Frequencies File", "file/sample_freqs", "Binary file containing sample frequencies as " "little-endian float32."};