Skip to content

Commit

Permalink
vfmted
Browse files Browse the repository at this point in the history
  • Loading branch information
skeris committed Aug 28, 2024
1 parent 2bf03fb commit 8baa9ee
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 78 deletions.
59 changes: 28 additions & 31 deletions vlib/x/benchmark/benchmark.v
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ const default_duration = time.second
// Benchmark represent all significant data for benchmarking. Provide clear way for getting result in convinient way by exported methods
@[noinit]
pub struct Benchmark {
pub mut:
n i64 // Number of iterations. Set explicitly or computed from expected time of benchmarking
bench_func fn()! @[required] // function for benchmarking
bench_time time.Duration // benchmark duration
is_parallel bool // if true every bench_func run in separate coroutine
benchmark_result BenchmarkResult // accumulator of benchmark metrics
timer_on bool // inner flag of time recording
start_time time.Time // start timestamp of timer
duration time.Duration // expected time of benchmark process
failed bool // flag of bench_func failure. true if one of bench_func run failed
start_memory usize // memory status on start benchmark
start_allocs usize // size of object allocated on heap
pub mut:
n i64 // Number of iterations. Set explicitly or computed from expected time of benchmarking
bench_func fn () ! @[required] // function for benchmarking
bench_time time.Duration // benchmark duration
is_parallel bool // if true every bench_func run in separate coroutine
benchmark_result BenchmarkResult // accumulator of benchmark metrics
timer_on bool // inner flag of time recording
start_time time.Time // start timestamp of timer
duration time.Duration // expected time of benchmark process
failed bool // flag of bench_func failure. true if one of bench_func run failed
start_memory usize // memory status on start benchmark
start_allocs usize // size of object allocated on heap
}

// Benchmark.new - constructor of benchmark
Expand All @@ -29,8 +29,8 @@ pub struct Benchmark {
// - n - number of iterations. set if you know how many runs of function you need. if qou don't know how many you need - set 0
// - duration - by default 1s. expecting duration of all benchmark runs. doesn't work if is_parallel == true
// - is_parallel - if true, every bench_func run in separate coroutine
pub fn Benchmark.new(bench_func fn()!, n i64, duration time.Duration, is_parallel bool) !Benchmark{
if bench_func == voidptr(0) {
pub fn Benchmark.new(bench_func fn () !, n i64, duration time.Duration, is_parallel bool) !Benchmark {
if bench_func == unsafe { nil } {
return error('Benchmark function cannot be empty')
}

Expand All @@ -39,16 +39,16 @@ pub fn Benchmark.new(bench_func fn()!, n i64, duration time.Duration, is_paralle
}

return Benchmark{
n:n
bench_func: bench_func
bench_time: if duration > 0 {duration} else {default_duration}
n: n
bench_func: bench_func
bench_time: if duration > 0 { duration } else { benchmark.default_duration }
is_parallel: is_parallel
}
}

// run_benchmark - function for start benchmarking
// run benchmark n times, or duration time
pub fn (mut b Benchmark) run_benchmark(){
pub fn (mut b Benchmark) run_benchmark() {
// run bench_func one time for heat up processor cache and get elapsed time for n prediction
b.run_n(1)

Expand Down Expand Up @@ -107,8 +107,8 @@ fn (mut b Benchmark) run_n(n i64) {
// if one execution failed print err, set failed flag and stop execution
b.failed = true
// workaround for consider unsuccesful runs
b.n -= n-i
eprintln('Error: $err')
b.n -= n - i
eprintln('Error: ${err}')
return
}
}
Expand All @@ -128,21 +128,18 @@ fn (mut b Benchmark) run_n(n i64) {
spawnwg.done()
}
workwg.wait()

}

// stop timer and collect data
b.stop_timer()
}

fn run_in_one_time(mut workwg &sync.WaitGroup, mut spawnwg &sync.WaitGroup, f fn()!){
fn run_in_one_time(mut workwg sync.WaitGroup, mut spawnwg sync.WaitGroup, f fn () !) {
defer {
workwg.done()
}
spawnwg.wait()
f() or {
return
}// TODO: add error handling
f() or { return } // TODO: add error handling
}

// predict_n - predict number of executions to estimate duration
Expand Down Expand Up @@ -189,7 +186,7 @@ fn (mut b Benchmark) reset_timer() {
// starttimer - register start measures of memory
fn (mut b Benchmark) start_timer() {
// you do not need to start timer that already started
if !b.timer_on{
if !b.timer_on {
b.start_time = time.now()
b.start_memory = gc_memory_use()
b.start_allocs = gc_heap_usage().bytes_since_gc
Expand All @@ -199,7 +196,7 @@ fn (mut b Benchmark) start_timer() {

// stop_timer - accumulate menchmark data
fn (mut b Benchmark) stop_timer() {
if b.timer_on{
if b.timer_on {
// accumulate delta time of execution
b.duration += time.since(b.start_time)
// accumulate memory growth
Expand All @@ -213,10 +210,10 @@ fn (mut b Benchmark) stop_timer() {
// BenchmarkResult - struct for represent result of benchmark
struct BenchmarkResult {
pub mut:
n i64 // iterations count
t time.Duration // elapsed time
mem usize // all allocated memory
allocs usize // heap allocated memory
n i64 // iterations count
t time.Duration // elapsed time
mem usize // all allocated memory
allocs usize // heap allocated memory
}

// ns_per_op - elapsed time in nanoseconds per iteration
Expand Down
91 changes: 44 additions & 47 deletions vlib/x/benchmark/benchmark_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import time
// if n == 0, n predict == 1
fn test_predict_n_zero() {
mut b := Benchmark{
n: 0,
duration: 0,
bench_time: time.second,
bench_func: fn()!{},
n: 0
duration: 0
bench_time: time.second
bench_func: fn () ! {}
}
expected := 1
println(b.predict_n())
Expand All @@ -18,10 +18,10 @@ fn test_predict_n_zero() {
// n can't be more 1000000000
fn test_predict_n_limit() {
mut b := Benchmark{
n: 10000000000,
duration: 0,
bench_time: time.second,
bench_func: fn()!{},
n: 10000000000
duration: 0
bench_time: time.second
bench_func: fn () ! {}
}
expected := 1000000000
assert b.predict_n() == expected
Expand All @@ -30,19 +30,19 @@ fn test_predict_n_limit() {
// test prediction for slow bench function
fn test_slow_fn() {
mut b := Benchmark{
duration: time.second,
bench_func: fn()!{},
duration: time.second
bench_func: fn () ! {}
}
assert b.predict_n() == 1
}

// if bench_func cause error set failed true, n = 1
fn test_fn_with_error() {
f := fn() ! {
f := fn () ! {
return error('error')
}
mut bench := Benchmark.new(f, 0, 0, false) or {
eprintln('Error creating benchmark: $err')
eprintln('Error creating benchmark: ${err}')
return
}

Expand All @@ -52,13 +52,13 @@ fn test_fn_with_error() {
assert bench.benchmark_result.n == 1
}

fn test_n_must_be_over_1(){
f := fn() ! {
fn test_n_must_be_over_1() {
f := fn () ! {
mut i := 0
i++
}
mut bench := Benchmark.new(f, 0, 0, false) or {
eprintln('Error creating benchmark: $err')
eprintln('Error creating benchmark: ${err}')
return
}

Expand All @@ -67,13 +67,13 @@ fn test_n_must_be_over_1(){
assert bench.benchmark_result.n > 1
}

fn test_n(){
f := fn() ! {
fn test_n() {
f := fn () ! {
mut i := 0
i++
}
mut bench := Benchmark.new(f, 1000, 0, false) or {
eprintln('Error creating benchmark: $err')
eprintln('Error creating benchmark: ${err}')
return
}

Expand All @@ -82,12 +82,12 @@ fn test_n(){
assert bench.benchmark_result.n == 1000
}

fn test_max_bench_time(){
f := fn() ! {
time.sleep(500* time.millisecond)
fn test_max_bench_time() {
f := fn () ! {
time.sleep(500 * time.millisecond)
}
mut bench := Benchmark.new(f, 0, 0, false) or {
eprintln('Error creating benchmark: $err')
eprintln('Error creating benchmark: ${err}')
return
}

Expand All @@ -98,13 +98,13 @@ fn test_max_bench_time(){
}

fn test_performance() {
scheduler := [func_1,func_2,func_3]
expected := [false,false,false]
scheduler := [func_1, func_2, func_3]
expected := [false, false, false]
mut actual := []bool{}

for i in scheduler{
for i in scheduler {
mut bench := Benchmark.new(i, 0, 0, false) or {
eprintln('Error creating benchmark: $err')
eprintln('Error creating benchmark: ${err}')
return
}

Expand All @@ -113,58 +113,55 @@ fn test_performance() {
}

assert expected.len == actual.len
for i:=0;i<expected.len;i++{
for i := 0; i < expected.len; i++ {
assert expected[i] == actual[i]
}

}

fn func_1() !{
fn func_1() ! {
mut arr := []int{}
appender(mut arr)
assert arr.len == 10
}

fn appender(mut arr []int){
if arr.len==10{
fn appender(mut arr []int) {
if arr.len == 10 {
return
}
arr << 1
appender(mut arr)
}

fn func_2() !{
fn func_2() ! {
target := 2
arr := [1,2,3,4,5,6,7,8,9,10]
arr := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

mut left := 0
mut right := arr.len-1
mut right := arr.len - 1

for left<=right{
mid :=left+(right-left)/2
if arr[mid] == target{
for left <= right {
mid := left + (right - left) / 2
if arr[mid] == target {
return
}
if arr[mid]<target{
if arr[mid] < target {
left = mid + 1
}
if arr[mid]>target{
if arr[mid] > target {
right = mid - 1
}
}
return
}

fn func_3() ! {
mut arr := [10, 2, 13, 4, 5, 16, 7, 1, 9, 20]

fn func_3() !{
mut arr := [10,2,13,4,5,16,7,1,9,20]

for i :=0; i<arr.len-1;i++{
for j:=0;j<arr.len-i-1;j++{
if arr[j] > arr[j+1]{
arr[j],arr[j+1]=arr[j+1],arr[j]
for i := 0; i < arr.len - 1; i++ {
for j := 0; j < arr.len - i - 1; j++ {
if arr[j] > arr[j + 1] {
arr[j], arr[j + 1] = arr[j + 1], arr[j]
}
}
}
}

0 comments on commit 8baa9ee

Please sign in to comment.