I’ve got an application with a WebSocket in JS that is handling some stream of data. My application then pulls that data on user demand and displays it.
I’ve noticed that every time the data is pulled, a reference to the copied object is kept internally by Skulpt, leading to a memory leak over time. This leak persists no matter if the passed object is a string (then it’s leaked in Skulpt’s str() builtin), a dict (dict() builtin), or list.
To try and circumvent this I thought of passing a dict from Python to a JS function, having it fill the data, and then using it back in Python so to avoid returning a new object from JS. This made me notice that the dictionary on the Python end doesn’t reflect changes made by JS.
I created a MRE in the clone link below. The code has a button that when pressed calls a JS script function with a Python dict. The JS function returns a random string and adds a value to the passed dictionary. The Python code then finally throws the result into a textbox. The returned string needs to be random to force a new string allocation and not let any constant-string optimizations happen under the hood. This chain of events serves to mock the on demand pulling of information from my WebSocket.
By running the cloned app and repeatedly pressing the button you can observe the following findings:
the new key added to the dict by the JS function is absent after its return.
monitoring the app with memory profiling (I tested with both firefox and Chrome’s developer tools) shows every press of the button causes the returned value to be leaked as it remains referenced internally by Skulpt. This memory isn’t freed, and the more you press the more the “baseline” memory consumption grows.
I tried deling the dict in the Python code, explicitly marking references as null or undefined in the JS code, and various other techniques but the root cause is that Skulpt keeps holding on to references after I’m done with them and marked them as such.
tl;dr:
is it possible to populate a dict passed from Python to JS?
returning a value from JS to Python leaks memory. How to handle?
Thanks for reporting, i’ve moved to bug reports.
This is an issue you’ve found with how Skulpt interns strings.
I’ll update this thread with any updates.
I think the post is really 2 questions, and I’d recommend creating a separate thread about Python dicts not getting updated.
This’ll make it easier for others to reply to that specific question.
I’m aware of an issue with interned strings but your post also mentions problems with dict and list. I’m not aware of issues with either of these objects. Are you able to demonstrate the issue with these data structures? (Do ensure that you profile the memory after running garbage collection).
You can easily reproduce in the app I linked by returning a dict instead of a string, and putting the random string as a value in the dict. I can make another app and put a clone link if that helps.
I followed your steps and observed the random_str is still referenced after garbage collection. You’re right though that it’s not clear if the dict itself is still being referenced, just that the retainer for the internal string now resides within dict().