Finding why an object is so big

I had an incident where some property in Perspective was triggering WebSocket failures in Designer for being too big. I was seeing errors like this in Designer logs:

10:26:55.578 [Browser Thread: f73b9d02-a4fb-46e7-90f8-5c8d71526b74] INFO  Perspective.SessionProps - store.Channel: Websocket connection closed. code=1009, wasClean=false, reason=Text message too large: (actual) 2,102,688 > (configured max text message size) 2,097,152, codeMeaning=Message Too Big, codeDescription=The endpoint is terminating the connection because a data frame was received that is too large.

I was having trouble figuring out which property, though. (We have a LOT of session.custom properties...)

With a tiny bit of tweaking, I was able to quickly change the "object sanitizer" script into an "object sizer" script:

from sys import getsizeof

def get_object_size(element):
    element_size = getsizeof(element)
    if hasattr(element, '__iter__'):
        if hasattr(element, 'keys'):
            return element_size + sum(get_object_size(element[k]) for k in element.keys())
        else:
            return element_size + sum(get_object_size(x) for x in element)
    return element_size

It only reports the total sizes for the next layer down. So, you may have to drill-down a few times if you have heavily nested items.

I made a binding with a script transform like this:

	suspect = self.custom
	result = {}
	for k in suspect.keys():
		result[k] = shared.utils.get_object_size(suspect[k])
	return result

I let that binding run once, figured out the worst top-level item, then tweaked the suspect = line to point at that, and kept drilling down on the suspect until it was obvious which property had exploded in size.

I don't fully trust getsizeof, but I couldn't find a better Java library size function quickly and I didn't need exact results, just a hint of who was BIG. (Java is not my strong area...)

Mostly posting this as a helpful debug tool if someone else bumps into a similar issue.