Ctrl K
ComunidadGuías…

bench/bench_closure.v

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
module main

import time
import sync
import os
import runtime
import v.util.version

// Define closure type alias
type ClosureFN = fn () int

// Test closures with different capture sizes
fn create_closure_small() ClosureFN {
	a := 0
	return fn [a] () int {
		return a
	}
}

fn create_closure_medium() ClosureFN {
	a, b, c, d := 1, 2, 3, 4
	return fn [a, b, c, d] () int {
		return a + b - c * d
	}
}

struct LargeData {
	array [10]int
}

fn create_closure_large() ClosureFN {
	data := LargeData{
		array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]!
	}
	return fn [data] () int {
		mut sum := 0
		for i in 0 .. 10 {
			sum += data.array[i]
		}
		return sum
	}
}

// Result structs
struct TestResult {
	test_name   string
	iterations  int
	time_ms     i64
	ops_per_sec f64 // Operations per second
	notes       string
}

struct MemoryResult {
	test_name         string
	count             int
	start_mem_kb      int
	end_mem_kb        int
	delta_kb          int
	bytes_per_closure int
	check_sum         int
}

// Benchmark group - returns result structs
fn benchmark_closure_creation(iterations int) []TestResult {
	mut results := []TestResult{}

	// Test small closure creation
	mut start := time.ticks()
	for _ in 0 .. iterations {
		_ = create_closure_small()
	}
	small_time := time.ticks() - start
	mut ops_per_sec := f64(iterations) * 1000.0 / f64(small_time)
	results << TestResult{'Small Closure Creation', iterations, small_time, ops_per_sec, ''}

	// Test medium closure creation
	start = time.ticks()
	for _ in 0 .. iterations {
		_ = create_closure_medium()
	}
	medium_time := time.ticks() - start
	ops_per_sec = f64(iterations) * 1000.0 / f64(medium_time)
	results << TestResult{'Medium Closure Creation', iterations, medium_time, ops_per_sec, ''}

	// Test large closure creation
	large_iter := iterations / 10
	start = time.ticks()
	for _ in 0 .. large_iter {
		_ = create_closure_large()
	}
	large_time := time.ticks() - start
	ops_per_sec = f64(large_iter) * 1000.0 / f64(large_time)
	results << TestResult{'Large Closure Creation', large_iter, large_time, ops_per_sec, ''} // , "Equivalent iterations: ${iterations/10}"}
	return results
}

fn benchmark_closure_call(iterations int) []TestResult {
	mut results := []TestResult{}

	closure_small := create_closure_small()
	closure_medium := create_closure_medium()
	closure_large := create_closure_large()

	// Test small closure call
	mut start := time.ticks()
	for _ in 0 .. iterations {
		_ = closure_small()
	}
	small_time := time.ticks() - start
	mut ops_per_sec := f64(iterations) * 1000.0 / f64(small_time)
	results << TestResult{'Small Closure Call', iterations, small_time, ops_per_sec, ''}

	// Test medium closure call
	start = time.ticks()
	for _ in 0 .. iterations {
		_ = closure_medium()
	}
	medium_time := time.ticks() - start
	ops_per_sec = f64(iterations) * 1000.0 / f64(medium_time)
	results << TestResult{'Medium Closure Call', iterations, medium_time, ops_per_sec, ''}

	// Test large closure call
	large_iter := iterations / 10
	start = time.ticks()
	for _ in 0 .. large_iter {
		_ = closure_large()
	}
	large_time := time.ticks() - start
	ops_per_sec = f64(large_iter) * 1000.0 / f64(large_time)
	results << TestResult{'Large Closure Call', large_iter, large_time, ops_per_sec, ''}

	return results
}

fn benchmark_threaded_creation(threads int, iterations_per_thread int) TestResult {
	total_iterations := threads * iterations_per_thread

	mut wg := sync.new_waitgroup()
	wg.add(threads)

	start := time.ticks()

	for _ in 0 .. threads {
		go fn [mut wg, iterations_per_thread] () {
			defer { wg.done() }
			for _ in 0 .. iterations_per_thread {
				_ = create_closure_medium()
			}
		}()
	}

	wg.wait()
	elapsed := time.ticks() - start
	ops_per_sec := f64(total_iterations) * 1000.0 / f64(elapsed)

	return TestResult{
		test_name:   'Multi-threaded Creation'
		iterations:  total_iterations
		time_ms:     elapsed
		ops_per_sec: ops_per_sec
		notes:       'Threads: ${threads} Iterations per thread: ${iterations_per_thread}'
	}
}

fn baseline_call_performance(iterations int) TestResult {
	start := time.ticks()
	for _ in 0 .. iterations {
		_ = normal_function()
	}
	elapsed := time.ticks() - start
	ops_per_sec := f64(iterations) * 1000.0 / f64(elapsed)

	return TestResult{
		test_name:   'Normal Function Call'
		iterations:  iterations
		time_ms:     elapsed
		ops_per_sec: ops_per_sec
		notes:       'Baseline'
	}
}

fn benchmark_memory_usage(count int) MemoryResult {
	mut closures := []ClosureFN{}
	start_mem := runtime.used_memory() or { panic(err) }

	for i in 0 .. count {
		the_closure := create_closure_medium()
		closures << the_closure

		if i % 1000 == 0 {
			_ = the_closure()
		}
	}

	end_mem := runtime.used_memory() or { panic(err) }
	delta := int(end_mem) - int(start_mem)
	bytes_per_closure := delta / count

	// Calculate verification sum
	mut check_sum := 0
	n := if closures.len < 100 { closures.len } else { 100 }
	for idx in 0 .. n {
		check_sum += closures[idx]()
	}

	return MemoryResult{
		test_name:         'Closure Memory Overhead'
		count:             count
		start_mem_kb:      int(start_mem / 1024)
		end_mem_kb:        int(end_mem / 1024)
		delta_kb:          delta / 1024
		bytes_per_closure: bytes_per_closure
		check_sum:         check_sum
	}
}

fn normal_function() int {
	return 42
}

// Format performance data for readability
fn format_perf(ops_per_sec f64) string {
	if ops_per_sec >= 1_000_000 {
		return '${ops_per_sec / 1_000_000:5.2f} Mop/s'
	} else if ops_per_sec >= 1_000 {
		return '${ops_per_sec / 1_000:5.2f} Kop/s'
	} else {
		return '${ops_per_sec:5.2f} op/s'
	}
}

fn print_results_table(results []TestResult, title string) {
	println('|---------------------------|------------|----------|--------------|--------------|')
	for res in results {
		perf_str := format_perf(res.ops_per_sec)
		println('| ${res.test_name:-25} | ${res.iterations:10} | ${res.time_ms:8} | ${perf_str:-12} | ${res.notes:-12} |')
	}
}

fn main() {
	println('# V Language Closure Performance Benchmark Report')

	// Configurable test parameters
	base_iter := 100_000_000 // 100 million iterations
	creation_iter := 10_000_000 // 1 million iterations
	mem_count := 100_000
	threads := 8
	thread_iter := 125_000

	// Execute tests
	baseline_result := baseline_call_performance(base_iter)
	creation_results := benchmark_closure_creation(creation_iter)
	call_results := benchmark_closure_call(base_iter)
	thread_result := benchmark_threaded_creation(threads, thread_iter)
	mem_result := benchmark_memory_usage(mem_count)

	// Print result tables
	println('\n## 1. Closure Performance Analysis')
	println('| Test Name                 | Iterations | Time(ms) | Ops/sec      | Notes        |')
	print_results_table([baseline_result], '1. Performance Baseline')
	print_results_table(creation_results, '2. Closure Creation Performance')
	print_results_table(call_results, '3. Closure Call Performance')
	print_results_table([thread_result], '4. Multi-threaded Performance')

	// Print memory results
	println('\n## 2. Memory Overhead Analysis')
	println('| Test Name               | Closure Count | Start Mem(KB) | End Mem(KB) | Delta(KB) | Bytes/Closure |')
	println('|-------------------------|---------------|---------------|------------|-----------|---------------|')
	println('| ${mem_result.test_name:-20} | ${mem_result.count:13} | ${mem_result.start_mem_kb:13} | ${mem_result.end_mem_kb:10} | ${mem_result.delta_kb:9} | ${mem_result.bytes_per_closure:13} |')
	println('\n**Verification Sum: ${mem_result.check_sum}** (Calculated from random sample of 100 closures)')

	println('\n## Test Environment')
	println('- V Language Version: ${version.full_v_version(false)}')
	println('- CPU Cores: ${runtime.nr_cpus()}')
	println('- System Memory: ${runtime.total_memory()! / 1024 / 1024} MB')
	println('- Operating System: ${os.user_os()}')
	println('\n> Test Time: ${time.now().format_ss_micro()}')
}