diff --git a/benchmarks/stdlib/sort/quicksort.c3 b/benchmarks/stdlib/sort/quicksort.c3 index 7a674659b..57d8b281d 100644 --- a/benchmarks/stdlib/sort/quicksort.c3 +++ b/benchmarks/stdlib/sort/quicksort.c3 @@ -8,7 +8,7 @@ fn void init() @init set_benchmark_max_iterations(10_000); } -fn void! quicksort_bench() @benchmark +fn void quicksort_bench() @benchmark { // test set: 500 numbers between 0 and 99; int[] data = { diff --git a/lib/std/core/runtime.c3 b/lib/std/core/runtime.c3 index bec99160d..df0f01489 100644 --- a/lib/std/core/runtime.c3 +++ b/lib/std/core/runtime.c3 @@ -22,7 +22,8 @@ struct SliceRaw usz len; } -def BenchmarkFn = fn void!(); +def BenchmarkFn = fn void!() @if($$OLD_TEST); +def BenchmarkFn = fn void() @if(!$$OLD_TEST); struct BenchmarkUnit { @@ -59,7 +60,7 @@ fn void set_benchmark_max_iterations(uint value) @builtin benchmark_max_iterations = value; } -fn bool run_benchmarks(BenchmarkUnit[] benchmarks) +fn bool run_benchmarks(BenchmarkUnit[] benchmarks) @if($$OLD_TEST) { int benchmarks_passed = 0; int benchmark_count = benchmarks.len; @@ -132,6 +133,62 @@ fn bool run_benchmarks(BenchmarkUnit[] benchmarks) return benchmark_count == benchmarks_passed; } +fn bool run_benchmarks(BenchmarkUnit[] benchmarks) @if(!$$OLD_TEST) +{ + usz max_name; + + foreach (&unit : benchmarks) + { + if (max_name < unit.name.len) max_name = unit.name.len; + } + + usz len = max_name + 9; + + DString name = dstring::temp_with_capacity(64); + name.append_repeat('-', len / 2); + name.append(" BENCHMARKS "); + name.append_repeat('-', len - len / 2); + + io::printn(name); + + name.clear(); + + long sys_clock_started; + long sys_clock_finished; + long sys_clocks; + Clock clock; + + foreach(unit : benchmarks) + { + defer name.clear(); + name.appendf("Benchmarking %s ", unit.name); + name.append_repeat('.', max_name - unit.name.len + 2); + io::printf("%s ", name.str_view()); + + for (uint i = 0; i < benchmark_warmup_iterations; i++) + { + unit.func() @inline; + } + + clock = std::time::clock::now(); + sys_clock_started = $$sysclock(); + + for (uint i = 0; i < benchmark_max_iterations; i++) + { + unit.func() @inline; + } + + sys_clock_finished = $$sysclock(); + NanoDuration nano_seconds = clock.mark(); + sys_clocks = sys_clock_finished - sys_clock_started; + + io::printfn("[COMPLETE] %.2f ns, %.2f CPU's clocks", (float)nano_seconds / benchmark_max_iterations, (float)sys_clocks / benchmark_max_iterations); + } + + io::printfn("\n%d benchmark%s run.\n", benchmarks.len, benchmarks.len > 1 ? "s" : ""); + return true; +} + fn bool default_benchmark_runner() { @pool() @@ -140,7 +197,8 @@ fn bool default_benchmark_runner() }; } -def TestFn = fn void!(); +def TestFn = fn void!() @if($$OLD_TEST); +def TestFn = fn void() @if(!$$OLD_TEST); struct TestUnit { @@ -191,7 +249,7 @@ fn void test_panic(String message, String file, String function, uint line) libc::longjmp(&test_context.buf, 1); } -fn bool run_tests(TestUnit[] tests) +fn bool run_tests(TestUnit[] tests) @if($$OLD_TEST) { usz max_name; foreach (&unit : tests) @@ -239,6 +297,50 @@ fn bool run_tests(TestUnit[] tests) return test_count == tests_passed; } +fn bool run_tests(TestUnit[] tests) @if(!$$OLD_TEST) +{ + usz max_name; + foreach (&unit : tests) + { + if (max_name < unit.name.len) max_name = unit.name.len; + } + quicksort(tests, &cmp_test_unit); + + TestContext context; + test_context = &context; + + PanicFn old_panic = builtin::panic; + defer builtin::panic = old_panic; + builtin::panic = &test_panic; + int tests_passed = 0; + int test_count = tests.len; + DString name = dstring::temp_with_capacity(64); + usz len = max_name + 9; + name.append_repeat('-', len / 2); + name.append(" TESTS "); + name.append_repeat('-', len - len / 2); + io::printn(name); + name.clear(); + foreach(unit : tests) + { + defer name.clear(); + name.appendf("Testing %s ", unit.name); + name.append_repeat('.', max_name - unit.name.len + 2); + io::printf("%s ", name.str_view()); + (void)io::stdout().flush(); + if (libc::setjmp(&context.buf) == 0) + { + unit.func(); + io::printn("[ok]"); + tests_passed++; + } + } + io::printfn("\n%d test%s run.\n", test_count, test_count > 1 ? "s" : ""); + io::printfn("Test Result: %s. %d passed, %d failed.", + tests_passed < test_count ? "FAILED" : "ok", tests_passed, test_count - tests_passed); + return test_count == tests_passed; +} + fn bool default_test_runner() { @pool() diff --git a/releasenotes.md b/releasenotes.md index 9a01f6dd8..d15efc1ba 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -23,6 +23,7 @@ - Improved `#foo` resolution inside of the compiler. - Deprecated '&' macro arguments. - Deprecate `fn void! main() type main functions. +- Deprecate old `void!` @benchmark and @test functions. ### Fixes - Fix case trying to initialize a `char[*]*` from a String. diff --git a/resources/examples/benchmarks.c3 b/resources/examples/benchmarks.c3 index 7ed2102a1..c44e76b84 100644 --- a/resources/examples/benchmarks.c3 +++ b/resources/examples/benchmarks.c3 @@ -1,21 +1,21 @@ import std::thread; -fn void! bench1() @benchmark +fn void bench1() @benchmark { - return std::thread::sleep_ms(1); + std::thread::sleep_ms(1)!!; } -fn void! bench123456789() @benchmark +fn void bench123456789() @benchmark { - return std::thread::sleep_ms(2); + std::thread::sleep_ms(2)!!; } -fn void! long_name_bench() @benchmark +fn void long_name_bench() @benchmark { - return std::thread::sleep_ms(3); + std::thread::sleep_ms(3)!!; } -fn void! very_long_name_bench() @benchmark +fn void very_long_name_bench() @benchmark { return std::thread::sleep_ms(10); } diff --git a/src/build/build.h b/src/build/build.h index d1fd6b35f..b7af75318 100644 --- a/src/build/build.h +++ b/src/build/build.h @@ -218,6 +218,13 @@ typedef enum SHOW_BACKTRACE_ON = 1 } ShowBacktrace; +typedef enum +{ + OLD_TEST_NOT_SET = -1, + OLD_TEST_OFF = 0, + OLD_TEST_ON = 1 +} OldTest; + typedef enum { SIZE_OPTIMIZATION_NOT_SET = -1, @@ -471,6 +478,7 @@ typedef struct BuildOptions_ OptimizationSetting optsetting; DebugInfo debug_info_override; ShowBacktrace show_backtrace; + OldTest old_test; ArchOsTarget arch_os_target_override; SafetyLevel safety_level; PanicLevel panic_level; @@ -624,6 +632,7 @@ typedef struct EmitStdlib emit_stdlib; LinkLibc link_libc; ShowBacktrace show_backtrace; + OldTest old_test; StripUnused strip_unused; DebugInfo debug_info; MergeFunctions merge_functions; @@ -705,6 +714,7 @@ static BuildTarget default_build_target = { .arch_os_target = ARCH_OS_TARGET_DEFAULT, .debug_info = DEBUG_INFO_NOT_SET, .show_backtrace = SHOW_BACKTRACE_NOT_SET, + .old_test = OLD_TEST_NOT_SET, .use_stdlib = USE_STDLIB_NOT_SET, .link_libc = LINK_LIBC_NOT_SET, .emit_stdlib = EMIT_STDLIB_NOT_SET, diff --git a/src/build/build_options.c b/src/build/build_options.c index f5a5aa382..0b559982c 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -125,6 +125,7 @@ static void usage(bool full) PRINTF(" --optsize=