abench.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Copyright (c) 2021, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/NumericLimits.h>
  7. #include <AK/Types.h>
  8. #include <LibAudio/Loader.h>
  9. #include <LibCore/ArgsParser.h>
  10. #include <LibCore/ElapsedTimer.h>
  11. #include <LibCore/File.h>
  12. #include <LibCore/System.h>
  13. #include <LibMain/Main.h>
  14. #include <stdio.h>
  15. // The Kernel has problems with large anonymous buffers, so let's limit sample reads ourselves.
  16. static constexpr size_t MAX_CHUNK_SIZE = 1 * MiB / 2;
  17. ErrorOr<int> serenity_main(Main::Arguments args)
  18. {
  19. StringView path {};
  20. int sample_count = -1;
  21. Core::ArgsParser args_parser;
  22. args_parser.set_general_help("Benchmark audio loading");
  23. args_parser.add_positional_argument(path, "Path to audio file", "path");
  24. args_parser.add_option(sample_count, "How many samples to load at maximum", "sample-count", 's', "samples");
  25. args_parser.parse(args);
  26. TRY(Core::System::unveil(Core::File::absolute_path(path), "r"));
  27. TRY(Core::System::unveil(nullptr, nullptr));
  28. TRY(Core::System::pledge("stdio recvfd rpath"));
  29. auto maybe_loader = Audio::Loader::create(path);
  30. if (maybe_loader.is_error()) {
  31. warnln("Failed to load audio file: {}", maybe_loader.error().description);
  32. return 1;
  33. }
  34. auto loader = maybe_loader.release_value();
  35. Core::ElapsedTimer sample_timer { true };
  36. u64 total_loader_time = 0;
  37. int remaining_samples = sample_count > 0 ? sample_count : NumericLimits<int>::max();
  38. unsigned total_loaded_samples = 0;
  39. for (;;) {
  40. if (remaining_samples > 0) {
  41. sample_timer = sample_timer.start_new();
  42. auto samples = loader->get_more_samples(min(MAX_CHUNK_SIZE, remaining_samples));
  43. auto elapsed = static_cast<u64>(sample_timer.elapsed());
  44. total_loader_time += static_cast<u64>(elapsed);
  45. if (!samples.is_error()) {
  46. remaining_samples -= samples.value().size();
  47. total_loaded_samples += samples.value().size();
  48. if (samples.value().size() == 0)
  49. break;
  50. } else {
  51. warnln("Error while loading audio: {}", samples.error().description);
  52. return 1;
  53. }
  54. } else
  55. break;
  56. }
  57. auto time_per_sample = static_cast<double>(total_loader_time) / static_cast<double>(total_loaded_samples) * 1000.;
  58. auto playback_time_per_sample = (1. / static_cast<double>(loader->sample_rate())) * 1000'000.;
  59. outln("Loaded {:10d} samples in {:06.3f} s, {:9.3f} µs/sample, {:6.1f}% speed (realtime {:9.3f} µs/sample)", total_loaded_samples, static_cast<double>(total_loader_time) / 1000., time_per_sample, playback_time_per_sample / time_per_sample * 100., playback_time_per_sample);
  60. return 0;
  61. }