diff --git a/cmd/tools/vtest-all.v b/cmd/tools/vtest-all.v index 97d839b706..60be08b0a0 100644 --- a/cmd/tools/vtest-all.v +++ b/cmd/tools/vtest-all.v @@ -263,6 +263,15 @@ fn get_all_commands() []Command { rmfile: 'v.c' } } + $if linux { + res << Command{ + line: '$vexe vlib/v/tests/bench/bench_stbi_load.v && prlimit -v10485760 vlib/v/tests/bench/bench_stbi_load' + okmsg: 'STBI load does not leak with GC on, when loading images multiple times (use < 10MB)' + runcmd: .execute + contains: 'logo.png 1000 times.' + rmfile: 'vlib/v/tests/bench/bench_stbi_load' + } + } $if !windows { res << Command{ line: '$vexe -raw-vsh-tmp-prefix tmp vlib/v/tests/script_with_no_extension' diff --git a/thirdparty/stb_image/stbi.c b/thirdparty/stb_image/stbi.c index abf6539926..a7b6b25500 100644 --- a/thirdparty/stb_image/stbi.c +++ b/thirdparty/stb_image/stbi.c @@ -1,5 +1,19 @@ #define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION + +#include + +extern void * stbi__callback_malloc(size_t size); +extern void * stbi__callback_realloc(void *ptr, size_t size); +extern void stbi__callback_free(void *ptr); + +#define STBI_MALLOC(sz) stbi__callback_malloc(sz) +#define STBI_REALLOC(p,newsz) stbi__callback_realloc(p,newsz) +#define STBI_FREE(p) stbi__callback_free(p) +#define STBIW_MALLOC(sz) stbi__callback_malloc(sz) +#define STBIW_REALLOC(p,newsz) stbi__callback_realloc(p,newsz) +#define STBIW_FREE(p) stbi__callback_free(p) + #include "stb_image.h" #include "stb_image_write.h" @@ -19,4 +33,5 @@ void write_force_png_filter(int level){ void write_tga_with_rle(int level) { stbi_write_tga_with_rle = level; -} \ No newline at end of file +} + diff --git a/vlib/stbi/stbi.c.v b/vlib/stbi/stbi.c.v index dbadf43fda..2ca04952c3 100644 --- a/vlib/stbi/stbi.c.v +++ b/vlib/stbi/stbi.c.v @@ -4,6 +4,31 @@ module stbi +[if trace_stbi_allocations ?] +fn trace_allocation(message string) { + eprintln(message) +} + +[export: 'stbi__callback_malloc'] +fn cb_malloc(s usize) voidptr { + res := unsafe { malloc(isize(s)) } + trace_allocation('> stbi__callback_malloc: $s => ${ptr_str(res)}') + return res +} + +[export: 'stbi__callback_realloc'] +fn cb_realloc(p voidptr, s usize) voidptr { + res := unsafe { v_realloc(p, isize(s)) } + trace_allocation('> stbi__callback_realloc: ${ptr_str(p)} , $s => ${ptr_str(res)}') + return res +} + +[export: 'stbi__callback_free'] +fn cb_free(p voidptr) { + trace_allocation('> stbi__callback_free: ${ptr_str(p)}') + unsafe { free(p) } +} + #flag -I @VEXEROOT/thirdparty/stb_image #include "stb_image.h" #include "stb_image_write.h" diff --git a/vlib/v/tests/bench/bench_stbi_load.v b/vlib/v/tests/bench/bench_stbi_load.v new file mode 100644 index 0000000000..cedb117e52 --- /dev/null +++ b/vlib/v/tests/bench/bench_stbi_load.v @@ -0,0 +1,19 @@ +import os +import stbi + +fn load_image(path string) { + img := stbi.load(path) or { return } + assert img.ok + // unsafe { img.free() } +} + +fn main() { + pid := os.getpid() + image_path := os.args[1] or { '${@VEXEROOT}/examples/assets/logo.png' } + for i in 1 .. 1001 { + if i % 100 == 0 { + println('pid: $pid | Loaded $image_path $i times.') + } + load_image(image_path) + } +}