117 lines
2.8 KiB
Odin

package demo
TRACY_ENABLE :: #config(TRACY_ENABLE, false)
when !TRACY_ENABLE {
#panic("TRACY_ENABLE need to be set to true for this demo to be useful.")
}
import "core:fmt"
import "core:time"
import "core:thread"
import "core:mem"
import "core:sync"
import "core:strings"
import "core:math/rand"
import "base:runtime"
import tracy ".."
/*
Dummy example to show using multiple threads with Tracy.
Build with: odin build . -define:TRACY_ENABLE=true
*/
random_generator_using_user_index_as_seed :: proc() -> runtime.Random_Generator {
@thread_local random_state: runtime.Default_Random_State
random_state = rand.create(u64(1 + context.user_index)) // 0 value means "use random seed", hence the +1
return runtime.default_random_generator(&random_state)
}
main :: proc() {
// For demo purposes, use a known seed for each thread
context.user_index = 0
context.random_generator = random_generator_using_user_index_as_seed()
tracy.SetThreadName("main");
NUM_WORKERS :: 3;
sync.barrier_init(&bar, 1 + NUM_WORKERS);
for i in 1..=NUM_WORKERS {
context.user_index = i;
thread.run(worker, context);
}
// Profile heap allocations with Tracy for this context.
context.allocator = tracy.MakeProfiledAllocator(
self = &tracy.ProfiledAllocatorData{},
callstack_size = 5,
backing_allocator = context.allocator,
secure = true
)
for {
// Marks the end of the frame. This is optional. Useful for
// applications which has a concept of a frame.
defer tracy.FrameMark();
{
// No name given receives the name of the calling procedure
tracy.Zone();
ptr, _ := random_alloc();
random_sleep();
free(ptr);
// Do some deliberate leaking
_, err := new(int);
}
// Sync all workers to current frame.
sync.barrier_wait(&bar);
}
}
worker :: proc() {
context.random_generator = random_generator_using_user_index_as_seed()
thread_name := strings.clone_to_cstring(fmt.tprintf("worker%i", context.user_index));
defer delete(thread_name);
tracy.SetThreadName(thread_name);
for {
{
// No name given receives the name of the calling procedure
tracy.Zone();
random_sleep();
}
{
tracy.ZoneN("worker doing stuff");
random_sleep();
}
{
// Name + Color. Colors in 0xRRGGBB format. 0 means "no color" (use a value
// close to 0 for black).
tracy.ZoneNC("worker doing stuff", 0xff0000);
random_sleep();
}
// sync with main thread for next frame
sync.barrier_wait(&bar);
}
}
bar : sync.Barrier;
random_sleep :: proc() {
time.sleep(time.Duration(rand.int_max(25)) * time.Millisecond);
}
random_alloc :: proc() -> (rawptr, mem.Allocator_Error) {
return mem.alloc(1 + rand.int_max(1024));
}