Closed AlecHaring closed 2 years ago
I've simplified the demo:
import sciter
from sciter.capi.scvalue import SCITER_VALUE
def memory_leak():
"""
Memory leak demo
"""
while True:
large_list = [0] * 100_000
sciter_array_struct = SCITER_VALUE * 1
sciter_array = sciter_array_struct()
sv = sciter.Value(large_list)
sv.copy_to(sciter_array[0])
sv.clear()
if __name__ == '__main__':
memory_leak()
Essentially each struct VALUE
shall be initialized by ValueInit(&val)
and freed by ValueClear(&val)
Seems like sciter_array[0] is not cleared.
Ah, I see. That makes a lot of sense now that you point it out. I really appreciate the nudge in the right direction.
sv
's value is copied into sciter_array[0]
's position in memory. sv
is cleaned up properly, but, as you said, sciter_array
is not.
I've modified the above demo to the following:
import ctypes
import sciter
from sciter.value import _api
from sciter.capi.scvalue import SCITER_VALUE
def memory_leak():
"""
Memory leak demo
"""
while True:
large_list = [0] * 100_000
sciter_array_struct = SCITER_VALUE * 1
sciter_array = sciter_array_struct()
sv = sciter.Value(large_list)
sv.copy_to(sciter_array[0])
sv.clear()
# free sciter_array from memory
ptr = ctypes.pointer(sciter_array[0])
_api.ValueClear(ptr)
if __name__ == '__main__':
memory_leak()
And the problem went away.
So, now that that is figured out, I'll revise Value.pack_args to make it properly clean up after itself and will make a PR.
Oh. Thanks for the investigation, it's a total loss.
Merged, will be in 0.6.9
The data that's passed to
sciter.Value.pack_args
, and then passed to_api.ValueCopy
is seemingly never cleaned up.Here's a demo that calls
sciter.Window.call_function
in an infinite loop with fake data:test.htm:
The
sciter.value
object that wraps the data is garbage collected, resulting in_api.ValueClear
being called, but that doesn't seem to actually clear it from memory. Running the above demo for 5 minutes consumed 500 MB of memory