[Closed] Struct creation leaks
I know that…
see yourself:
struct TestStruct
(
a = 0, b = pi, c = x_axis
)
gc()
(
t = timestamp()
h = heapfree
for k=1 to 10000 do
(
s = TestStruct()
)
format "time:% heap:%
" (timestamp() - t) (h - heapfree)
)
time:7 heap:1329904L
as you can see it’s pretty big leaking for small struct and not really big amount.
now there’s some trick:
(
t = timestamp()
h = heapfree
a = TestStruct()
for k=1 to 10000 do
(
s = copy a
)
format "time:% heap:%
" (timestamp() - t) (h - heapfree)
)
time:5 heap:648912L
it’s two times better, but still a lot of leaking.
Any another ideas how to decrease memory usage or free the memory after without gc ?
The value that leaks is the point3 (x_axis in this case).
I guess point2, color, point4, matrix, etc. all would also leak.
If you can have these constant values defined before creation I think it should not leak (that much).
Perhaps structures have a minimal fixed heap allocation and cg() doesn’t kick in automatically??
Doesn’t this code create Shallow Copies of the Structure?
I think it should be:
(
struct TestStruct
(
a = 0, b = pi, c = x_axis
)
gc()
st=timestamp(); sh=heapfree
c = x_axis
for k = 1 to 10000 do
(
s = TestStruct c:c
)
format "time:% heap:%
" (timestamp()-st) (sh-heapfree)
)
time:6 heap:658928L
This would create unique instances of the structure and also keep the memory low.
it might be empty structure… the problem that ‘internal data’ is not collectable. i can’t find any way to free it after creation
struct TestStruct
(
on clone do ()
)
gc()
(
t = timestamp()
h = heapfree
for k=1 to 10000 do
(
s = TestStruct()
)
format "time:% heap:%
" (timestamp() - t) (h - heapfree)
)
I’ve tested with bigger structures, which do not create any of the values that leaks, but have several functions, and they don’t leak. The used heap is very similar having an empty structure or one with many functions, empty variables or variables set to int, float, etc.
As soon as you add a static point3, color, matrix, etc. The heap usage starts increasing.
As far as I can see, what leaks are the values mentioned earlier.
The only way I find to free the heap is ‘gc light:on’, but you already mentioned that you don’t want to use cg().
If you delete the loop and write “s = TestStruct()” 10000 times, you’ll get the same.
And if you write ‘s1 = TestStruct()’, ‘s2 = TestStruct()’,… ‘s10000 = TestStruct()’, too.
As Jorge has said, “Perhaps structures have a minimal fixed heap allocation”.
See these examples. I would assume both would use the same (or close) memory footprint, but they don’t.
(
struct struct1
(
a=[0,0,0], b=[0,0,0], c=[0,0,0]
)
struct struct2
(
a1=0,a2=0,a3=0,
b1=0,b2=0,b3=0,
c1=0,c2=0,c3=0
)
gc();st=timestamp(); sh=heapfree
for j = 1 to 100000 do
(
s = struct1()
)
format "time:% heap:%
" (timestamp()-st) (sh-heapfree)
gc();st=timestamp(); sh=heapfree
for j = 1 to 100000 do
(
s = struct2()
)
format "time:% heap:%
" (timestamp()-st) (sh-heapfree)
)
time:124 heap:25647584L
time:68 heap:6446120L
6Mb against 24Mb
the system allocates memory kinda strange for me…
run these lines
struct str (a = [0,0,0])
a = str()
b = copy a
b.a = [1,0,0]
a.a
b = copy a
b.a.x = 1
a.a
as you can see ‘copy’ makes a ‘copy’ of pointers to structure properties, but not a copy of ‘pointer’ values.
that’s probably why it makes a structure not ‘fully’ collectable
The issue seems to be solved in Max 2017.
I get these values for the code of post #7
time:313 heap:3808304L
time:138 heap:6800848L
This past weekend i was playing with ‘collecting’ max values (array, struct, point2(3,4), matrix3, etc.)
the values those are derived from MaxHeapOperators are easy to collect excepting one thing… I will tell about it later.
Array and structs are more complicated because they can be nested. So the only solution I see is a recursion… where I met another problem.
The theory –
all max Values are derived from Collectable, which has virtual method collect . It’s the thing that should care about its collection. By default it’s empty (do noting).
So… all pointer type value are doing something (sometimes) and { delete this; } which makes sense.
But Numbers (Integer, Float, Integer64, etc.) override (!) default but keep them empty. ( void collect(); ) . The same behavior is for ‘abstract’ values – undefined, ok, unsupplied, etc.
It’s probably worked formerly, but today it causes to crash.
so I have three problems:
#1 Some value classes cause max to crash
#2 a value can have instances which are getting collection at the same time
#3 arrays and structs are special
(later I found #4 but it’s a different story)
…
be continued…
Ahhh… I forgot to say – finally I’ve almost solved the task. Arrays and Structs are not leaking … no… they are still leaking, but I can collect them on-the-fly without GC and because of that without losing a performance.
I said ‘almost’ … because [B]#4/B is not solved well yet.
…
be continued