From 338f4c884a451f7ff2f6b3c4054b1a290bbb67ca Mon Sep 17 00:00:00 2001 From: Nicholas Lukasevich Date: Tue, 16 May 2023 19:49:27 -0400 Subject: [PATCH] file_write_benchmark --- Makefile | 5 ++- src/file_write_benchmark.cpp | 78 ++++++++++++++++++++++++++++++++++++ src/scoped_timer.hpp | 58 +++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 src/file_write_benchmark.cpp create mode 100644 src/scoped_timer.hpp diff --git a/Makefile b/Makefile index a253353..b880983 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ DEPS = $(OBJS:.o=.d) default: all -all: next_cluster make_image make_states simulate_one simulate_many +all: next_cluster make_image make_states simulate_one simulate_many file_write_benchmark core = $(addprefix $(BIN_DIR)/, fregex.o logger.o pgm8.o program_options.o simulation_misc.o simulation_parse_state.o simulation_run.o simulation_save_state.o util.o term.o) @@ -53,6 +53,9 @@ simulate_many: $(core) $(BIN_DIR)/simulate_many_main.o tests: $(core) $(BIN_DIR)/ntest.o $(BIN_DIR)/testing_main.o @$(CXX) $(CXXFLAGS) -o $(BIN_DIR)/$@ $^ $(LDFLAG) @echo 'compiling tests...' +file_write_benchmark: $(BIN_DIR)/file_write_benchmark.o + @$(CXX) $(CXXFLAGS) -o $(BIN_DIR)/file_write_benchmark $^ $(LDFLAG) + @echo 'compiling file_write_benchmark...' $(BIN_DIR): @mkdir -p $(BIN_DIR) diff --git a/src/file_write_benchmark.cpp b/src/file_write_benchmark.cpp new file mode 100644 index 0000000..a1962b9 --- /dev/null +++ b/src/file_write_benchmark.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "primitives.hpp" +#include "scoped_timer.hpp" + +int main() { + u64 width = 10'000; + u64 height = 10'000; + u64 num_pixels = width * height; + + std::vector pixels{}; + + srand(u32(time(NULL))); + + { + scoped_timer timer("generating random pixel data", std::cout); + + pixels.reserve(num_pixels); + + for (u64 i = 0; i < num_pixels; ++i) + pixels.push_back((uint8_t)rand()); + } + + // FILE + { + FILE *file = fopen("stdio_FILE.bin", "wb"); + assert(file); + { + scoped_timer timer("stdio FILE", std::cout); + assert(fwrite(pixels.data(), pixels.size(), sizeof(u8), file)); + } + fclose(file); + std::filesystem::remove("stdio_FILE.bin"); + } + + // std::fstream + { + std::fstream file("std_fstream.bin", std::ios::binary | std::ios::out); + assert(file); + { + scoped_timer timer("std::fstream", std::cout); + file.write((char const *)pixels.data(), std::streamsize(pixels.size())); + } + std::filesystem::remove("std_fstream.bin"); + } + + // std::fstream + { + std::ofstream file("std_ofstream.bin", std::ios::binary); + assert(file); + { + scoped_timer timer("std::ofstream", std::cout); + file.write((char const *)pixels.data(), std::streamsize(pixels.size())); + } + std::filesystem::remove("std_ofstream.bin"); + } + + // linux write + { + int fd = open("linux_write.bin", O_WRONLY | O_CREAT | O_TRUNC, 0644); + assert(fd != -1); + { + scoped_timer timer("linux write", std::cout); + assert(write(fd, pixels.data(), pixels.size()) == i64(pixels.size())); + } + close(fd); + std::filesystem::remove("linux_write.bin"); + } +} \ No newline at end of file diff --git a/src/scoped_timer.hpp b/src/scoped_timer.hpp new file mode 100644 index 0000000..d30537d --- /dev/null +++ b/src/scoped_timer.hpp @@ -0,0 +1,58 @@ +#ifndef NLUKA_SCOPEDTIMER_HPP +#define NLUKA_SCOPEDTIMER_HPP + +#include +#include +#include +#include + +namespace scoped_timer_unit +{ + typedef uint32_t value_type; + + value_type constexpr + SECONDS = 1'000'000'000, + MILLISECONDS = 1'000'000, + MICROSECONDS = 1'000, + NANOSECONDS = 1; +}; + +template +class scoped_timer +{ + public: + scoped_timer(char const *const label, std::ostream &os) + : m_label{label}, + m_os{os}, + m_start{std::chrono::steady_clock::now()} + {} + + scoped_timer(scoped_timer const &) = delete; // copy constructor + scoped_timer &operator=(scoped_timer const &) = delete; // copy assignment + scoped_timer(scoped_timer &&) noexcept = delete; // move constructor + scoped_timer &operator=(scoped_timer &&) noexcept = delete; // move assignment + + ~scoped_timer() { + auto const end = std::chrono::steady_clock::now(); + auto const elapsed_nanos = end - m_start; + auto const elapsed_time_in_units = static_cast(elapsed_nanos.count() / TimerUnit); + + char const *unit_cstr; + switch (TimerUnit) { + case scoped_timer_unit::SECONDS: unit_cstr = "s"; break; + case scoped_timer_unit::MILLISECONDS: unit_cstr = "ms"; break; + case scoped_timer_unit::MICROSECONDS: unit_cstr = "us"; break; + case scoped_timer_unit::NANOSECONDS: unit_cstr = "ns"; break; + default: unit_cstr = nullptr; break; + } + + m_os << m_label << " took " << elapsed_time_in_units << unit_cstr << '\n'; + } + + private: + std::string_view const m_label; + std::ostream &m_os; + std::chrono::time_point const m_start; +}; + +#endif // NLUKA_SCOPEDTIMER_HPP