Utilities/allocate: Modernize the code a bit

Use LibCore ArgsParser to parse the parameters instead of using the raw
strings from the argv (Main::Arguments) array.

Also, use indicative names for variables in the code so the utility code
is more understandable.
This commit is contained in:
Liav A 2023-06-25 21:52:47 +03:00 committed by Jelle Raaijmakers
parent 75ae368896
commit b74cb569ec
2 changed files with 105 additions and 53 deletions

View file

@ -5,36 +5,31 @@ allocate - allocate memory
## Synopsis ## Synopsis
```**sh ```**sh
$ allocate [number [unit (B/KiB/MiB)]] $ allocate [--unit B/KiB/MiB/GiB] [--sleep-time N] [number]
``` ```
## Description ## Description
`allocate` allocates a specific amount of virtual memory (specified in `number` and `unit`, by default 50 MiB), It also writes to each allocated page and then sleeps for 10 seconds. It is primarily used to test the kernel's memory management capabilities. `allocate` allocates a specific amount of virtual memory. If nothing is specified
then it will allocate 100 bytes of memory.
If `number` is specified without `unit`, it will default to `number` of bytes.
It also writes to each allocated page and then sleeps for N seconds (by default 10).
It is primarily used to test the kernel's memory management capabilities.
## Arguments ## Options
* `number`: A number of `units` to allocate; the default is **50** * `-u`, `--size-unit`: Allocation's Size Unit (Base 2 units - B, KiB, MiB or GiB)
* `unit`: Data size unit, can be `B` (bytes), `KiB` (kibibytes) or `MiB` (mebibytes); the default is **MiB** * `-n`, `--sleep-time`: Number of seconds to sleep before freeing memory
## Examples ## Examples
```sh ```sh
$ allocate 100 MiB $ allocate 500
allocating memory (104857600 bytes)... allocating memory (500 bytes)...
done in 13ms done in 0ms
writing one byte to each page of allocated memory... writing one byte to each page of allocated memory...
step took 46ms (217.391304MiB/s) done in 0ms
step took 32ms (312.500000MiB/s) sleeping for 10 seconds...
step took 31ms (322.580645MiB/s)
step took 55ms (181.818181MiB/s)
step took 35ms (285.714285MiB/s)
step took 40ms (250.000000MiB/s)
step took 39ms (256.410256MiB/s)
step took 52ms (192.307692MiB/s)
step took 44ms (227.272727MiB/s)
done in 426ms
sleeping for ten seconds...
0 0
1 1
2 2
@ -47,5 +42,58 @@ sleeping for ten seconds...
9 9
done. done.
freeing memory... freeing memory...
done in 119ms done in 0ms
$ allocate 500 -u KiB
allocating memory (512000 bytes)...
done in 0ms
writing one byte to each page of allocated memory...
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
done in 4ms
sleeping for 10 seconds...
0
1
2
3
4
5
6
7
8
9
done.
freeing memory...
done in 0ms
$ allocate -u KiB -n 2 500
allocating memory (512000 bytes)...
done in 0ms
writing one byte to each page of allocated memory...
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
step took 1ms (46.875MiB/s)
done in 0ms
sleeping for 2 seconds...
0
1
done.
freeing memory...
done in 0ms
``` ```

View file

@ -1,81 +1,85 @@
/* /*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <AK/Format.h> #include <AK/Format.h>
#include <AK/Optional.h> #include <AK/Optional.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/ElapsedTimer.h> #include <LibCore/ElapsedTimer.h>
#include <LibMain/Main.h> #include <LibMain/Main.h>
#include <unistd.h> #include <unistd.h>
static void usage()
{
warnln("usage: allocate [number [unit (B/KiB/MiB)]]");
exit(1);
}
enum class Unit { enum class Unit {
Bytes, Bytes,
KiB, KiB,
MiB, MiB,
GiB,
}; };
ErrorOr<int> serenity_main(Main::Arguments arguments) ErrorOr<int> serenity_main(Main::Arguments arguments)
{ {
int count = 50; size_t iterations_count = 10;
auto unit = Unit::MiB; size_t allocation_size = 100;
auto unit = Unit::Bytes;
StringView chosen_unit {};
if (arguments.argc >= 2) { Core::ArgsParser args_parser;
auto number = arguments.strings[1].to_uint(); args_parser.add_option(chosen_unit, "Allocation's Size Unit in base 2 (B, KiB, MiB, GiB)", "unit", 'u', "unit");
if (!number.has_value()) { args_parser.add_option(iterations_count, "Number of seconds to sleep before freeing memory", "sleep-time", 'n', "seconds");
usage(); args_parser.add_positional_argument(allocation_size, "Allocation Size", "size", Core::ArgsParser::Required::No);
} args_parser.parse(arguments);
count = number.value();
}
if (arguments.argc >= 3) { if (!chosen_unit.is_null()) {
if (arguments.strings[2] == "B") if (chosen_unit == "B"sv) {
unit = Unit::Bytes; unit = Unit::Bytes;
else if (arguments.strings[2] == "KiB") } else if (chosen_unit == "KiB"sv) {
unit = Unit::KiB; unit = Unit::KiB;
else if (arguments.strings[2] == "MiB") } else if (chosen_unit == "MiB") {
unit = Unit::MiB; unit = Unit::MiB;
else } else if (chosen_unit == "GiB") {
usage(); unit = Unit::GiB;
} else {
args_parser.print_usage(stderr, arguments.strings[0]);
return 1;
}
} }
switch (unit) { switch (unit) {
case Unit::Bytes: case Unit::Bytes:
break; break;
case Unit::KiB: case Unit::KiB:
count *= KiB; allocation_size *= KiB;
break; break;
case Unit::MiB: case Unit::MiB:
count *= MiB; allocation_size *= MiB;
break;
case Unit::GiB:
allocation_size *= GiB;
break; break;
} }
outln("allocating memory ({} bytes)...", count); outln("allocating memory ({} bytes)...", allocation_size);
auto timer = Core::ElapsedTimer::start_new(); auto timer = Core::ElapsedTimer::start_new();
char* ptr = (char*)malloc(count); auto* ptr = reinterpret_cast<char*>(malloc(allocation_size));
if (!ptr) { if (!ptr) {
outln("failed."); outln("failed.");
return 1; return 1;
} }
outln("done in {}ms", timer.elapsed_milliseconds()); outln("done in {}ms", timer.elapsed_milliseconds());
auto pages = count / PAGE_SIZE; size_t pages_count = allocation_size / PAGE_SIZE;
auto step = pages / 10; auto step = pages_count / 10;
outln("writing one byte to each page of allocated memory..."); outln("writing one byte to each page of allocated memory...");
timer.start(); timer.start();
auto timer2 = Core::ElapsedTimer::start_new(); auto timer2 = Core::ElapsedTimer::start_new();
for (int i = 0; i < pages; ++i) { for (size_t page_index = 0; page_index < pages_count; ++page_index) {
ptr[i * PAGE_SIZE] = 1; ptr[page_index * PAGE_SIZE] = 1;
if (i != 0 && (i % step) == 0) { if (page_index != 0 && (page_index % step) == 0) {
auto ms = timer2.elapsed_milliseconds(); auto ms = timer2.elapsed_milliseconds();
if (ms == 0) if (ms == 0)
ms = 1; ms = 1;
@ -89,9 +93,9 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
} }
outln("done in {}ms", timer.elapsed_milliseconds()); outln("done in {}ms", timer.elapsed_milliseconds());
outln("sleeping for ten seconds..."); outln("sleeping for {} seconds...", iterations_count);
for (int i = 0; i < 10; i++) { for (unsigned iteration_index = 0; iteration_index < iterations_count; iteration_index++) {
outln("{}", i); outln("{}", iteration_index);
sleep(1); sleep(1);
} }
outln("done."); outln("done.");