Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions benchmarks/stdlib/core/string_trim.c3
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module string_trim_wars;

const String WHITESPACE_TARGET = " \n\t\r\f\va \tbcde\v\f\r\t\n ";
const String WHITESPACE_NUMERIC_TARGET = " 25290 0969 99a \tbcde12332 34 43 0000";

fn void initialize_bench() @init
{
set_benchmark_warmup_iterations(64);
set_benchmark_max_iterations(1 << 24);
}

macro void trim_bench($trim_str, String $target = WHITESPACE_TARGET) => @pool()
{
String s1;
String s2 = $target.tcopy();

runtime::@start_benchmark();

$switch:
$case @typeis($trim_str, String):
s1 = s2.trim($trim_str);
$case @typeis($trim_str, AsciiCharset):
s1 = s2.trim_charset($trim_str);
$default: $error "Unable to determine the right String `trim` operation to use.";
$endswitch

@volatile_load(s1);

runtime::@end_benchmark();
}


module string_trim_wars @benchmark;

fn void trim_control() => trim_bench(" "); // only spaces

fn void trim_whitespace_default() => trim_bench("\t\n\r "); // default set
fn void trim_whitespace_default_ordered() => trim_bench(" \n\t\r"); // default \w set, but ordered by expected freq

fn void trim_whitespace_bad() => trim_bench("\f\v\n\t\r "); // bad-perf ordering, all \w

fn void trim_whitespace_ordered_extended() => trim_bench(" \n\t\r\f\v"); // proposed ordering, all \w
fn void trim_charset_whitespace() => trim_bench(ascii::WHITESPACE_SET); // use charset, all \w

fn void trim_many() => trim_bench(" \n\t\r\f\v0123456789", WHITESPACE_NUMERIC_TARGET); // ordered, all \w + num
fn void trim_charset_many() => trim_bench(ascii::WHITESPACE_SET | ascii::NUMBER_SET, WHITESPACE_NUMERIC_TARGET); // set, all \w + num
47 changes: 31 additions & 16 deletions lib/std/core/runtime_benchmark.c3
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,24 @@ fn void set_benchmark_func_iterations(String func, uint value) @builtin

Clock benchmark_clock @local;
NanoDuration benchmark_nano_seconds @local;
long cycle_start @local;
long cycle_stop @local;
DString benchmark_log @local;
bool benchmark_warming @local;
uint this_iteration @local;

macro @start_benchmark() => benchmark_clock = std::time::clock::now();
macro @end_benchmark() => benchmark_nano_seconds = benchmark_clock.mark();
macro @start_benchmark()
{
benchmark_clock = std::time::clock::now();
cycle_start = $$sysclock();
}

macro @end_benchmark()
{
benchmark_nano_seconds = benchmark_clock.mark();
cycle_stop = $$sysclock();
}

macro @log_benchmark(msg, args...) => @pool()
{
if (benchmark_warming) return;
Expand Down Expand Up @@ -85,10 +97,6 @@ fn bool run_benchmarks(BenchmarkUnit[] benchmarks)

name.clear();

long sys_clock_started;
long sys_clock_finished;
long sys_clocks;

foreach (unit : benchmarks)
{
defer name.clear();
Expand All @@ -104,15 +112,14 @@ fn bool run_benchmarks(BenchmarkUnit[] benchmarks)
benchmark_warming = false;

NanoDuration running_timer;
sys_clock_started = $$sysclock();
benchmark_nano_seconds = {};
long total_clocks;

uint current_benchmark_iterations = bench_fn_iters[unit.name] ?? benchmark_max_iterations;
char[] perc_str = { [0..19] = ' ', [20] = 0 };
int perc = 0;
uint print_step = current_benchmark_iterations / 100;

for (this_iteration = 0; this_iteration < current_benchmark_iterations; ++this_iteration)
for (this_iteration = 0; this_iteration < current_benchmark_iterations; ++this_iteration, benchmark_nano_seconds = {})
{
if (0 == this_iteration % print_step) // only print right about when the % will update
{
Expand All @@ -127,23 +134,31 @@ fn bool run_benchmarks(BenchmarkUnit[] benchmarks)

unit.func() @inline;

if (!benchmark_nano_seconds) @end_benchmark();
if (benchmark_nano_seconds == (NanoDuration){}) @end_benchmark(); // only mark when it wasn't already by the unit.func

total_clocks += cycle_stop - cycle_start;
running_timer += benchmark_nano_seconds;
}

sys_clock_finished = $$sysclock();
sys_clocks = sys_clock_finished - sys_clock_started;

float clock_cycles = (float)sys_clocks / current_benchmark_iterations;
float clock_cycles = (float)total_clocks / current_benchmark_iterations;
float measurement = (float)running_timer / current_benchmark_iterations;
String[] units = { "nanoseconds", "microseconds", "milliseconds", "seconds" };

float adjusted_measurement = measurement;
while (adjusted_measurement > 1_000) adjusted_measurement /= 1_000;
float adjusted_runtime_total = (float)running_timer;
while (adjusted_runtime_total > 1_000) adjusted_runtime_total /= 1_000;

io::printf("\r%s ", name.str_view());
io::printfn("[COMPLETE] %.2f %s, %.2f CPU clocks, %d iterations",
adjusted_measurement, units[math::min(3, (int)math::floor(math::log(measurement, 1_000)))], clock_cycles, current_benchmark_iterations);
io::printfn(
"[COMPLETE] %.2f %s, %.2f CPU clocks, %d iterations (runtime %.2f %s)",
adjusted_measurement,
units[math::min(3, (int)math::floor(math::log(measurement, 1_000)))],
clock_cycles,
current_benchmark_iterations,
adjusted_runtime_total,
units[math::min(3, (int)math::floor(math::log((float)running_timer, 1_000)))],
);
}

io::printfn("\n%d benchmark%s run.\n", benchmarks.len, benchmarks.len > 1 ? "s" : "");
Expand Down
6 changes: 3 additions & 3 deletions lib/std/core/string.c3
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ fn String String.treplace(self, String needle, String new_str)
@pure
@return `a substring of the string passed in`
*>
fn String String.trim(self, String to_trim = "\t\n\r ")
fn String String.trim(self, String to_trim = " \n\t\r\f\v")
{
return self.trim_left(to_trim).trim_right(to_trim);
}
Expand Down Expand Up @@ -243,7 +243,7 @@ fn String String.trim_charset(self, AsciiCharset to_trim = ascii::WHITESPACE_SET
@pure
@return `a substring of the string passed in`
*>
fn String String.trim_left(self, String to_trim = "\t\n\r ")
fn String String.trim_left(self, String to_trim = " \n\t\r\f\v")
{
usz start = 0;
usz len = self.len;
Expand All @@ -260,7 +260,7 @@ fn String String.trim_left(self, String to_trim = "\t\n\r ")
@pure
@return `a substring of the string passed in`
*>
fn String String.trim_right(self, String to_trim = "\t\n\r ")
fn String String.trim_right(self, String to_trim = " \n\t\r\f\v")
{
usz len = self.len;
while (len > 0 && char_in_set(self[len - 1], to_trim)) len--;
Expand Down
Loading