v / cmd / v2 / guiprof / main.v
154 lines · 132 sloc · 3.96 KB · a76973f101edbe08f2df8b6ee19784ede8bfe966
Raw
1// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module main
5
6import gg
7import os
8import v2.profiler
9
10fn main() {
11 // Initialize profiler system
12 profiler.profiler_init()
13
14 // Create application state (on stack, like the working example)
15 mut app := App{}
16
17 // Check command line args for mode
18 args := os.args
19 if '--demo' in args {
20 app.demo_mode = true
21 app.live_mode = false
22 init_demo_data(mut app)
23 } else {
24 // Default to live mode - read from snapshot file
25 app.demo_mode = false
26 app.live_mode = true
27 }
28
29 // Create gg context
30 app.gg = gg.new_context(
31 width: window_width
32 height: window_height
33 create_window: true
34 window_title: 'V2 Allocation Profiler'
35 bg_color: bg_color
36 frame_fn: frame
37 event_fn: event_handler
38 user_data: &app
39 )
40
41 // Run the application
42 app.gg.run()
43}
44
45// frame is the frame callback for gg
46fn frame(mut app App) {
47 draw_frame(mut app)
48}
49
50// event_handler handles gg events
51fn event_handler(e &gg.Event, mut app App) {
52 handle_event(e, mut app)
53}
54
55// init_demo_data populates the profiler with simulated data for demonstration
56fn init_demo_data(mut app App) {
57 app.demo_mode = true
58 app.demo_frame = 0
59
60 // Create simulated frame and allocation data
61 app.cached_frames = []profiler.FrameData{cap: 100}
62 app.cached_allocs = []profiler.AllocRecord{cap: 500}
63
64 // Simulate 100 frames of allocation activity
65 mut total_live := u64(0)
66 mut peak := u64(0)
67 mut alloc_idx := 0
68 mut total_allocs := u64(0)
69 mut total_frees := u64(0)
70
71 for frame_num := 0; frame_num < 100; frame_num++ {
72 mut frame_data := profiler.FrameData{
73 frame_num: u64(frame_num)
74 }
75
76 // Simulate some allocations each frame
77 // More allocations early, fewer later (typical startup pattern)
78 num_allocs := if frame_num < 20 { 10 - frame_num / 4 } else { 2 + (frame_num % 3) }
79
80 for _ in 0 .. num_allocs {
81 // Random-ish allocation sizes
82 size := 64 + ((frame_num * 17 + alloc_idx * 31) % 4096)
83
84 app.cached_allocs << profiler.AllocRecord{
85 ptr: unsafe { voidptr(u64(0x1000) + u64(alloc_idx) * 0x100) }
86 size: size
87 frame: u64(frame_num)
88 file: ['main.v', 'parser.v', 'scanner.v', 'types.v', 'gen.v'][alloc_idx % 5]
89 line: 100 + (alloc_idx % 500)
90 timestamp: i64(frame_num) * 16_666_667 + i64(alloc_idx) * 1000
91 freed: false
92 }
93
94 frame_data.new_allocs << alloc_idx
95 frame_data.new_bytes += u64(size)
96 total_live += u64(size)
97 total_allocs++
98 alloc_idx++
99 }
100
101 // Simulate some frees (but not all - create some "leaks")
102 // Free some allocations from previous frames
103 if frame_num > 5 {
104 num_frees := num_allocs - 1 // Always free slightly fewer than we allocate
105 mut freed_count := 0
106 for i := 0; i < app.cached_allocs.len && freed_count < num_frees; i++ {
107 if !app.cached_allocs[i].freed && app.cached_allocs[i].frame < u64(frame_num - 3) {
108 // 80% chance to free
109 if (i * 7 + frame_num * 13) % 10 < 8 {
110 app.cached_allocs[i].freed = true
111 app.cached_allocs[i].free_frame = u64(frame_num)
112 frame_data.freed_idxs << i
113 frame_data.freed_bytes += u64(app.cached_allocs[i].size)
114 total_live -= u64(app.cached_allocs[i].size)
115 total_frees++
116 freed_count++
117 }
118 }
119 }
120 }
121
122 frame_data.live_bytes = total_live
123 if total_live > peak {
124 peak = total_live
125 }
126
127 app.cached_frames << frame_data
128 }
129
130 // Count leaks
131 mut leak_count := 0
132 for alloc in app.cached_allocs {
133 if !alloc.freed {
134 leak_count++
135 }
136 }
137
138 // Update stats
139 app.cached_stats = profiler.Statistics{
140 live_bytes: total_live
141 peak_bytes: peak
142 total_allocs: total_allocs
143 total_frees: total_frees
144 leak_count: leak_count
145 frame_count: 100
146 }
147}
148
149// update_demo_data simulates ongoing activity in demo mode
150fn update_demo_data(mut app App) {
151 // In demo mode, we just use the static simulated data
152 // For a more dynamic demo, we could add new frames here
153 app.demo_frame++
154}
155