// Copyright Epic Games, Inc. All Rights Reserved. #include "bench_cmd.h" #include "bench.h" #include #include #include #include #include #include #include #include namespace zen { BenchCommand::BenchCommand() { m_Options.add_options()("h,help", "Print help"); m_Options.add_options()("purge", "Purge standby memory (system cache)", cxxopts::value(m_PurgeStandbyLists)->default_value("false")); m_Options.add_options()("single", "Do not spawn child processes", cxxopts::value(m_SingleProcess)->default_value("false")); } BenchCommand::~BenchCommand() = default; int BenchCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ZEN_UNUSED(GlobalOptions); if (!ParseOptions(argc, argv)) { return 0; } #if ZEN_PLATFORM_WINDOWS if (m_PurgeStandbyLists) { bool Ok = false; zen::Stopwatch Timer; try { zen::bench::util::EmptyStandByList(); Ok = true; } catch (const zen::bench::util::elevation_required_exception&) { ZEN_CONSOLE("purging standby lists requires elevation. Will try launch as elevated process"); } catch (const std::exception& Ex) { ZEN_CONSOLE("ERROR: {}", Ex.what()); } if (!Ok && !m_SingleProcess) { try { zen::CreateProcOptions Cpo; Cpo.Flags = zen::CreateProcOptions::Flag_Elevated | zen::CreateProcOptions::Flag_NewConsole; std::filesystem::path CurExe{zen::GetRunningExecutablePath()}; if (zen::CreateProcResult Cpr = zen::CreateProc(CurExe, fmt::format("bench --purge --single"), Cpo)) { zen::ProcessHandle ProcHandle; ProcHandle.Initialize(Cpr); int ExitCode = ProcHandle.WaitExitCode(); if (ExitCode == 0) { Ok = true; } else { ZEN_CONSOLE("ERROR: Elevated child process failed with return code {}", ExitCode); } } } catch (const std::exception& Ex) { ZEN_CONSOLE("ERROR: {}", Ex.what()); } } if (Ok) { // TODO: could also add reporting on just how much memory was purged ZEN_CONSOLE("purged standby lists! (took {})", zen::NiceTimeSpanMs(Timer.GetElapsedTimeMs())); } } #endif return 0; } } // namespace zen