mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
Shell: Support time -n <iterations>
You can now specify a number of iterations when timing a command. The default value is 1 and behaves exactly as before. If the iteration count is greater than 1, the command will be executed that many times, and then you get a little timing report afterwards with the average runtime per iteration, and also the average runtime excluding the very first iteration. (Excluding the first iteration is useful when it's slowed down by cold caches, etc.) This is something I've been doing manually forever (running `time foo` and then eyeballing the results to headmath an average) and this makes that whole process so much nicer. :^)
This commit is contained in:
parent
96909f5200
commit
b9ab7a5095
Notes:
sideshowbarker
2024-07-19 01:59:31 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/b9ab7a50954
1 changed files with 40 additions and 6 deletions
|
@ -906,27 +906,61 @@ int Shell::builtin_time(int argc, const char** argv)
|
|||
{
|
||||
Vector<const char*> args;
|
||||
|
||||
int number_of_iterations = 1;
|
||||
|
||||
Core::ArgsParser parser;
|
||||
parser.add_option(number_of_iterations, "Number of iterations", "iterations", 'n', "iterations");
|
||||
parser.set_stop_on_first_non_option(true);
|
||||
parser.add_positional_argument(args, "Command to execute with arguments", "command", Core::ArgsParser::Required::Yes);
|
||||
|
||||
if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage))
|
||||
return 1;
|
||||
|
||||
if (number_of_iterations < 1)
|
||||
return 1;
|
||||
|
||||
AST::Command command;
|
||||
for (auto& arg : args)
|
||||
command.argv.append(arg);
|
||||
|
||||
auto commands = expand_aliases({ move(command) });
|
||||
|
||||
Core::ElapsedTimer timer;
|
||||
Vector<int> iteration_times;
|
||||
|
||||
int exit_code = 1;
|
||||
timer.start();
|
||||
for (auto& job : run_commands(commands)) {
|
||||
block_on_job(job);
|
||||
exit_code = job.exit_code();
|
||||
for (int i = 0; i < number_of_iterations; ++i) {
|
||||
Core::ElapsedTimer timer;
|
||||
timer.start();
|
||||
for (auto& job : run_commands(commands)) {
|
||||
block_on_job(job);
|
||||
exit_code = job.exit_code();
|
||||
}
|
||||
iteration_times.append(timer.elapsed());
|
||||
}
|
||||
warnln("Time: {} ms", timer.elapsed());
|
||||
|
||||
if (number_of_iterations == 1) {
|
||||
warnln("Time: {} ms", iteration_times.first());
|
||||
} else {
|
||||
float total_time = 0;
|
||||
for (auto time : iteration_times)
|
||||
total_time += static_cast<float>(time);
|
||||
float average = total_time / iteration_times.size();
|
||||
|
||||
float total_time_excluding_first = 0;
|
||||
for (size_t i = 1; i < iteration_times.size(); ++i)
|
||||
total_time_excluding_first += static_cast<float>(iteration_times[i]);
|
||||
float average_excluding_first = total_time_excluding_first / (iteration_times.size() - 1);
|
||||
|
||||
warnln("Timing report:");
|
||||
warnln("==============");
|
||||
warn("Command: ");
|
||||
for (auto& string : args)
|
||||
warn("{} ", string);
|
||||
warnln("");
|
||||
warnln("Average time: {} ms", average);
|
||||
warnln("Excluding first: {} ms", average_excluding_first);
|
||||
}
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue