| 1 | module bench |
| 2 | |
| 3 | import os |
| 4 | import time |
| 5 | |
| 6 | // C.getrusage declares the C getrusage symbol used by bench. |
| 7 | fn C.getrusage(who int, usage voidptr) int |
| 8 | |
| 9 | // Step represents step data used by bench. |
| 10 | pub struct Step { |
| 11 | pub: |
| 12 | name string |
| 13 | time_us i64 |
| 14 | ram_kb i64 |
| 15 | } |
| 16 | |
| 17 | // Bench represents bench data used by bench. |
| 18 | pub struct Bench { |
| 19 | mut: |
| 20 | steps []Step |
| 21 | total_sw time.StopWatch |
| 22 | step_sw time.StopWatch |
| 23 | } |
| 24 | |
| 25 | // new creates a new value for bench. |
| 26 | pub fn new() Bench { |
| 27 | return Bench{ |
| 28 | total_sw: time.new_stopwatch() |
| 29 | step_sw: time.new_stopwatch() |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | // step records a serial pipeline step. |
| 34 | pub fn (mut b Bench) step(name string) { |
| 35 | b.step_parallel(name, false) |
| 36 | } |
| 37 | |
| 38 | // step_parallel records a pipeline step, appending "(parallel)" to its name |
| 39 | // when the step actually ran across threads. |
| 40 | pub fn (mut b Bench) step_parallel(name string, parallel bool) { |
| 41 | elapsed_us := b.step_sw.elapsed().microseconds() |
| 42 | ram_mb := f64(current_rss_kb()) / 1024.0 |
| 43 | ms := f64(elapsed_us) / 1000.0 |
| 44 | label := if parallel { '${name} (parallel)' } else { name } |
| 45 | println(' ${label:-20s} ${ms:8.2f} ms ${ram_mb:6.0f} MB resident RAM') |
| 46 | b.steps << Step{ |
| 47 | name: label |
| 48 | time_us: elapsed_us |
| 49 | ram_kb: i64(ram_mb * 1024) |
| 50 | } |
| 51 | b.step_sw.restart() |
| 52 | } |
| 53 | |
| 54 | // print_report updates print report state for Bench. |
| 55 | pub fn (b &Bench) print_report() { |
| 56 | total_ms := f64(b.total_sw.elapsed().microseconds()) / 1000.0 |
| 57 | println(' ${'total':-20s} ${total_ms:8.2f} ms') |
| 58 | println('') |
| 59 | } |
| 60 | |
| 61 | // current_rss_kb returns current rss kb data for bench. |
| 62 | fn current_rss_kb() i64 { |
| 63 | $if macos { |
| 64 | return macos_peak_rss_kb() |
| 65 | } |
| 66 | $if linux { |
| 67 | return linux_rss_kb() |
| 68 | } |
| 69 | return 0 |
| 70 | } |
| 71 | |
| 72 | // macos_peak_rss_kb supports macos peak rss kb handling for bench. |
| 73 | fn macos_peak_rss_kb() i64 { |
| 74 | mut usage := [256]u8{} |
| 75 | if C.getrusage(0, &usage[0]) == 0 { |
| 76 | ru_maxrss := unsafe { *(&i64(&usage[32])) } |
| 77 | return ru_maxrss / 1024 |
| 78 | } |
| 79 | return 0 |
| 80 | } |
| 81 | |
| 82 | // linux_rss_kb supports linux rss kb handling for bench. |
| 83 | fn linux_rss_kb() i64 { |
| 84 | content := os.read_file('/proc/self/status') or { return 0 } |
| 85 | for line in content.split('\n') { |
| 86 | if line.starts_with('VmRSS:') { |
| 87 | parts := line.split_any(' \t').filter(it.len > 0) |
| 88 | if parts.len >= 2 { |
| 89 | return parts[1].i64() |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | return 0 |
| 94 | } |
| 95 | |