Staying aware of struct sizes; is there a better approach?

#assert(size_of(Entity) >   512, "INFO:  32MB @ 2^12 entities.")
#assert(size_of(Entity) <   768, "INFO:  48MB @ 2^12 entities.")
#assert(size_of(Entity) <  1024, "INFO:  64MB @ 2^12 entities.")

#assert(size_of(Globals) >   32*Megabyte, "INFO: Know this figure.")
#assert(size_of(Globals) <   64*Megabyte, "INFO: Know this figure.")
#assert(size_of(Globals) <  128*Megabyte, "INFO: Know this figure.")

I’m curious if others do this, and how you approach it.
Note that the first case is a > to ensure I couldn’t possibly shrink the structure below the last known (roughly) power of two.

The only unfortunate thing about this scheme is that I’ve managed to get in a situation where a struct can shrink on one platform and not others. For that reason, I think I’d just rather have a warning, but I’m not aware of a way to emit warnings.

Do do you do anything to stay mindful of related things?

1 Like

If you are talking about just printing warnings during runtime, I do something like this:

warn :: proc(cond: bool, msg: ..any, loc := #caller_location) {
	if cond {
		_msg := fmt.tprint(..msg)
		fmt.println(_msg, loc)
	}
}

warn(size_of(Entity) < 512, typeid_of(Entity), "INFO: 32MB @ 2^12 entities.")

// output
// Entity INFO: 32MB @ 2^12 entities. /home/xuul/Documents/projects/odin/scratch/scratch.odin(89:2)

Or (shameless plug incoming) if you are using my afmt library, you can have pretty yellow :grin:

warn :: proc(cond: bool, msg: ..any, loc := #caller_location) {
	if cond {
		_msg := afmt.tprint(..msg)
		afmt.println("-f[yellow]", _msg, loc)
	}
}

Update: Cause I’m a geek…
If you want printf capabilities do

// with fmt
warnf :: proc(cond: bool, _fmt: string, msg: ..any, loc := #caller_location) {
	if cond {
		_msg := fmt.tprintf(_fmt, ..msg)
		fmt.println(_msg, loc)
	}
}

// or with afmt for color
warnf :: proc(cond: bool, _fmt: string, msg: ..any, loc := #caller_location) {
	if cond {
		_msg := afmt.tprintf(_fmt, ..msg)
		afmt.println("-f[yellow]", _msg, loc)
	}
}

warnf(size_of(Entity) < 512, "%v size: %v %v", typeid_of(Entity), size_of(Entity), "INFO: 32MB @ 2^12 entities.")

Update: Fixed some brain damaged copy-n-pastes

1 Like

Seems my brain was severally damaged last night. I did not see the “#” in “#assert”, so my suggestions were way off the mark.

I couldn’t find a way to signal messages during compile time. The best I can think is to create a flag that you can turn on and off without having to comment/uncomment code. Worst case, an #assert breaks compiling when the flag is true. Then just recompile without the flag.

WARN :: #config(warn, false)

main :: proc() {
	when WARN {
		#assert(size_of(Entity) >   512, "INFO:  32MB @ 2^12 entities.")
	}
}

// build with
odin build . -define:warn=true
// you get #asserts triggered so you know the situation
// recompile without flag set, and no code changes

And if compiling on Linux, can execute a normal build if the first build command failed with the following, so it all happens in one line.

odin build . -define:warn=true || odin build .
// or
odin build . -define:warn=true || echo "warning occured - building again" && odin build .
1 Like