Forums > Javascript

memory consumption by js (?)

June 21, 2010 | 3:01 pm

I have a javascript function that gets called very often (with Task or from the patch with qmetro -> (function) -> js) and now and then Max would crash when the patch using this javascript is running. I suspect that something in the javascript or in the patch slowly but surely generates garbage and fills up memory, but I have no proof. Sometimes the memory consumption grows as patch is running and sometimes it isn’t and I don’t see the pattern.

I’m trying to localize the problem, without much success. But here is one of the tests I’ve come up with (it doesn’t crash, but it makes me wonder):

– Pasted Max Patch, click to expand. –

I start Max, it consumes about 50Mb memory (RSIZE in Activity Monitor), I open the script and switch on the metro that dumps a list into a javascript property and requests this property back. As the patch runs memory consumption by max slowly rises above 100Mb and eventually stops at some high number (say 113.50Mb). Stopping the metro usually frees some kilobytes of memory (to 112.96Mb), starting it again makes memory consumption rise again to some seemingly arbitrary level where it stops again.

This behavior isn’t very consistent: sometimes the memory consumption rises, sometimes not and the speed of consumtion is always different, just stoping the metro, waiting a bit and starting it again sometimes changes the behavior.

Max doesn’t crash, so I haven’t found the problem, but I wonder, what causes it to consume these additional 60Mb and why it stops eventually? The script that does crash Max has similar interface: Max requests the script to execute a function, the function calculates and returns a list of numbers back to Max.

I’ll try to make a minimal crashing test case now, but would appreciate any insights.


June 28, 2010 | 5:34 pm

While I can’t respond regarding your own js without actually seeing it, in the example you posted it looks like you’re just seeing the garbage collector in (in)action.


July 7, 2010 | 11:09 am

Yes, that’s probably it.

I still haven’t pinpoint where my own script keeps crashing, but here is a relevant portion of its backtrace at the last crash:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000020202020
Crashed Thread:  0

Thread 0 Crashed:
0   ???                           	0x20202020 0 + 538976288
1   com.cycling74.jsui            	0x18797dd2 js_addfuns + 501
2   com.cycling74.jsui            	0x18797fb0 jsmaxobj_newwith + 151
3   com.cycling74.jsui            	0x18799243 jspatcher_getproperty + 564
4   com.cycling74.MaxJSRef        	0x18813e31 js_GetProperty + 946
5   com.cycling74.MaxJSRef        	0x187b6ff3 js_Interpret + 28401
6   com.cycling74.MaxJSRef        	0x187be259 js_Invoke + 2059
7   com.cycling74.MaxJSRef        	0x187c4fba fun_apply + 886
8   com.cycling74.MaxJSRef        	0x187be1fa js_Invoke + 1964
9   com.cycling74.MaxJSRef        	0x187b8155 js_Interpret + 32851
10  com.cycling74.MaxJSRef        	0x187be259 js_Invoke + 2059
11  com.cycling74.MaxJSRef        	0x187be466 js_InternalInvoke + 181
12  com.cycling74.MaxJSRef        	0x187e115b JS_CallFunctionName + 202
13  com.cycling74.js              	0x1cd6d89b js_calljsfun + 1460
14  com.cycling74.js              	0x1cd6d9a3 js_doanything + 67
15  com.cycling74.MaxMSP          	0x000332b8 defer + 110
16  com.cycling74.MaxAPI          	0x00eefd64 defer_medium + 67
17  com.cycling74.js              	0x1cd6ddd2 js_messagehandler + 569
18  com.cycling74.js              	0x1cd6e031 js_anything + 47
19  com.cycling74.MaxMSP          	0x0001c538 typedmess_fun + 782
20  com.cycling74.MaxMSP          	0x00063b27 outlet_anything + 727
21  com.cycling74.MaxMSP          	0x0001c538 typedmess_fun + 782
22  com.cycling74.MaxMSP          	0x00063b27 outlet_anything + 727
23  com.cycling74.MaxMSP          	0x0004f33f through_scheduler_senditfun(through*, _sendargs*) + 59
24  com.cycling74.MaxMSP          	0x0004f3cb through_scheduler_sendit + 79
25  com.cycling74.MaxMSP          	0x0004f65f through_anything(through*, symbol*, short, atom*) + 65
26  com.cycling74.MaxMSP          	0x000b701e object_method_typedfun + 134
27  com.cycling74.MaxMSP          	0x000b70d7 object_method_typed + 127
28  com.cycling74.MaxAPI          	0x00efc3eb object_method_typed + 59
29  com.cycling74.jsui            	0x18796c7d js_dotypedmess + 354
30  com.cycling74.jsui            	0x1879793e js_messnamed + 106
31  com.cycling74.MaxJSRef        	0x187be1fa js_Invoke + 1964
32  com.cycling74.MaxJSRef        	0x187b8155 js_Interpret + 32851
33  com.cycling74.MaxJSRef        	0x187be259 js_Invoke + 2059
34  com.cycling74.MaxJSRef        	0x187be466 js_InternalInvoke + 181
35  com.cycling74.MaxJSRef        	0x187e1069 JS_CallFunction + 65
36  com.cycling74.jsui            	0x1879bcf9 jstask_qfn + 220
37  com.cycling74.MaxMSP          	0x0002a511 sched_dequeue + 119
38  com.cycling74.MaxMSP          	0x00012587 max_tick + 77
39  com.cycling74.MaxMSP          	0x001e0094 maxapplication_eventtimerproc(__EventLoopTimer*, void*) + 22
40  com.apple.CoreFoundation      	0x9540f8f5 CFRunLoopRunSpecific + 4469
41  com.apple.CoreFoundation      	0x9540faa8 CFRunLoopRunInMode + 88
42  com.apple.HIToolbox           	0x9736a2ac RunCurrentEventLoopInMode + 283
43  com.apple.HIToolbox           	0x97369ffe ReceiveNextEventCommon + 175
44  com.apple.HIToolbox           	0x974ad377 ReceiveNextEvent + 58
45  com.cycling74.MaxMSP          	0x002cd822 juce::juce_dispatchNextMessageOnSystemQueue(bool, bool) + 554
46  com.cycling74.MaxMSP          	0x002d73f7 juce::MessageManager::dispatchNextMessage(bool, bool*, bool) + 79
47  com.cycling74.MaxMSP          	0x002d74b6 juce::MessageManager::runDispatchLoop() + 42
48  com.cycling74.MaxMSP          	0x002d5e11 juce::JUCEApplication::main(juce::String&, juce::JUCEApplication*) + 605
49  com.cycling74.MaxMSP          	0x002d5eeb juce::JUCEApplication::main(int, char**, juce::JUCEApplication*) + 125
50  com.cycling74.MaxMSP          	0x001e04d8 main + 76
51  com.cycling74.MaxMSP          	0x00005c02 _start + 216
52  com.cycling74.MaxMSP          	0x00005b29 start + 41

I suspected garbage collector because of the jsmaxobj_newwith near the crash, but it could be something different of course.


July 7, 2010 | 11:14 am

on second thought, it’s not exactly the same place as I was experiencing before: it now crashes doing something in [jsui], but the patch I was talking about two weeks ago didn’t have any [jsui]. My new suspicion is that something corrupts interpreter’s memory and actual crash happens at some random moment. Time for more tests.


July 7, 2010 | 11:24 am

A couple more backtraces show that actual error always differ. And prior to the crash memory consumed by Max executable reaches something around 500Mb.

I’ll try to make a simple patch + script to show the problem.

Is there a way to force garbage collection from a script or C external?

Exception Type:  EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Crashed Thread:  0

Thread 0 Crashed:
0   ???                           	0x2129e000 0 + 556392448
1   com.cycling74.jsui            	0x028e8eef js_addfuns + 786
2   com.cycling74.jsui            	0x028e8fb0 jsmaxobj_newwith + 151
3   com.cycling74.jsui            	0x028ea243 jspatcher_getproperty + 564
4   com.cycling74.MaxJSRef        	0x02964e31 js_GetProperty + 946
5   com.cycling74.MaxJSRef        	0x02907ff3 js_Interpret + 28401
6   com.cycling74.MaxJSRef        	0x0290f259 js_Invoke + 2059
7   com.cycling74.MaxJSRef        	0x02909155 js_Interpret + 32851

...

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000000
Crashed Thread:  0

Thread 0 Crashed:
0   ???                           	0000000000 0 + 0
1   com.cycling74.jsui            	0x18715dd2 js_addfuns + 501
2   com.cycling74.jsui            	0x18715fb0 jsmaxobj_newwith + 151
3   com.cycling74.jsui            	0x187160e7 jspatcher_getnamed + 152
4   com.cycling74.MaxJSRef        	0x1873c1fa js_Invoke + 1964
5   com.cycling74.MaxJSRef        	0x18736155 js_Interpret + 32851
6   com.cycling74.MaxJSRef        	0x1873c259 js_Invoke + 2059
7   com.cycling74.MaxJSRef        	0x18742fba fun_apply + 886
8   com.cycling74.MaxJSRef        	0x1873c1fa js_Invoke + 1964

July 7, 2010 | 1:47 pm

Here we go, the simplified patch / script took an hour to crash but crash it did.

I’m not sure using dummy [jsui] objects was necessary to reproduce the crash, I’ll run another test now with panels instead.

EDIT: the original test-patch contains a typo, use 774.test-script2 instead.

Instructions: start the [qmetro] and switch to presentation mode.

The test-script.js animates the size of gui objects under its control to fit inside configured constraints. After some time it crashes randomly (see backtraces in this thread).

Interval Since Last Report:          3612 sec
Crashes Since Last Report:           1
Per-App Interval Since Last Report:  3454 sec
Per-App Crashes Since Last Report:   1

Date/Time:       2010-07-07 15:02:57.158 +0200
OS Version:      Mac OS X 10.5.8 (9L31a)
Report Version:  6
Anonymous UUID:  EF1E06D0-7BB7-41E8-BD0E-D3771AB1C369

Exception Type:  EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Crashed Thread:  0

Thread 0 Crashed:
0   ???                           	0x203ee000 0 + 540991488
1   com.cycling74.js              	0x1723b237 js_addfuns + 786
2   com.cycling74.js              	0x1723b2f8 jsmaxobj_newwith + 151
3   com.cycling74.js              	0x1723b42f jspatcher_getnamed + 152
4   com.cycling74.MaxJSRef        	0x181ad1fa js_Invoke + 1964
5   com.cycling74.MaxJSRef        	0x181a7155 js_Interpret + 32851
6   com.cycling74.MaxJSRef        	0x181ad259 js_Invoke + 2059
7   com.cycling74.MaxJSRef        	0x181b3fba fun_apply + 886
8   com.cycling74.MaxJSRef        	0x181ad1fa js_Invoke + 1964
9   com.cycling74.MaxJSRef        	0x181a7155 js_Interpret + 32851
10  com.cycling74.MaxJSRef        	0x181ad259 js_Invoke + 2059
11  com.cycling74.MaxJSRef        	0x181ad466 js_InternalInvoke + 181
12  com.cycling74.MaxJSRef        	0x181d015b JS_CallFunctionName + 202
13  com.cycling74.js              	0x1723e89b js_calljsfun + 1460
14  com.cycling74.js              	0x1723e9a3 js_doanything + 67
15  com.cycling74.MaxMSP          	0x000332b8 defer + 110
16  com.cycling74.MaxAPI          	0x00eefd64 defer_medium + 67
17  com.cycling74.js              	0x1723edd2 js_messagehandler + 569
18  com.cycling74.js              	0x1723f031 js_anything + 47
19  com.cycling74.MaxMSP          	0x0001c538 typedmess_fun + 782
20  com.cycling74.MaxMSP          	0x00063b27 outlet_anything + 727
21  com.cycling74.MaxMSP          	0x0001c538 typedmess_fun + 782
22  com.cycling74.MaxMSP          	0x0001ca69 typedmess + 83
23  com.cycling74.MaxMSP          	0x0001d0d5 aeval + 893
24  com.cycling74.MaxMSP          	0x000085e0 atombuf_eval + 152
25  com.cycling74.MaxAPI          	0x00efb0a7 atombuf_eval + 60
26  com.cycling74.message         	0x172a40ad jmessage_atombuf_eval + 429
27  com.cycling74.message         	0x172a415e jmessage_list + 116
28  com.cycling74.MaxMSP          	0x00063e59 outlet_list + 649
29  com.cycling74.MaxAPI          	0x00eee748 outlet_list + 60
30  com.cycling74.pak             	0x0281ea1f pak_output + 162
31  com.cycling74.pak             	0x0281ec47 pak_anything + 188
32  com.cycling74.pak             	0x0281eca3 pak_int + 63
33  com.cycling74.MaxMSP          	0x000466de proxy_int(proxy*, long) + 98
34  com.cycling74.MaxMSP          	0x000649a8 outlet_int + 690
35  com.cycling74.MaxAPI          	0x00eee694 outlet_int + 38
36  com.cycling74.toggle          	0x172e525e jtoggle_int + 45
37  com.cycling74.toggle          	0x172e52cc jtoggle_bang + 33
38  com.cycling74.MaxMSP          	0x00064f48 outlet_bang + 952
39  com.cycling74.MaxMSP          	0x00064e32 outlet_bang + 674
40  com.cycling74.MaxAPI          	0x00eee64d outlet_bang + 31
41  com.cycling74.metro           	0x02923b37 metro_out + 77
42  com.cycling74.MaxMSP          	0x0002a511 sched_dequeue + 119
43  com.cycling74.MaxMSP          	0x00012587 max_tick + 77
44  com.cycling74.MaxMSP          	0x001e0094 maxapplication_eventtimerproc(__EventLoopTimer*, void*) + 22
45  com.apple.CoreFoundation      	0x9540f8f5 CFRunLoopRunSpecific + 4469
46  com.apple.CoreFoundation      	0x9540faa8 CFRunLoopRunInMode + 88
47  com.apple.HIToolbox           	0x9736a2ac RunCurrentEventLoopInMode + 283
48  com.apple.HIToolbox           	0x97369ffe ReceiveNextEventCommon + 175
49  com.apple.HIToolbox           	0x974ad377 ReceiveNextEvent + 58
50  com.cycling74.MaxMSP          	0x002cd822 juce::juce_dispatchNextMessageOnSystemQueue(bool, bool) + 554
51  com.cycling74.MaxMSP          	0x002d73f7 juce::MessageManager::dispatchNextMessage(bool, bool*, bool) + 79
52  com.cycling74.MaxMSP          	0x002d74b6 juce::MessageManager::runDispatchLoop() + 42
53  com.cycling74.MaxMSP          	0x002d5e11 juce::JUCEApplication::main(juce::String&, juce::JUCEApplication*) + 605
54  com.cycling74.MaxMSP          	0x002d5eeb juce::JUCEApplication::main(int, char**, juce::JUCEApplication*) + 125
55  com.cycling74.MaxMSP          	0x001e04d8 main + 76
56  com.cycling74.MaxMSP          	0x00005c02 _start + 216
57  com.cycling74.MaxMSP          	0x00005b29 start + 41

July 7, 2010 | 2:41 pm

In a neighbour thread I found out that calling gc() allows to force garbage collection, which I added to the layout script. It seems to have helped (the memory consumption seems restrained) although I need longer test to be sure (may be it’s some sort of slow hysteresis).


July 7, 2010 | 3:04 pm

yes, it is hysteresis, peak memory consumption slowly grows even with regular calls to gc(), but the growth rate is low enough to not be a problem in real life use of the patch, I think.


July 7, 2010 | 3:23 pm

I guess something in JS is leaking. Which example is the most current?

-A


July 7, 2010 | 4:43 pm

the (774.test-script2.maxpat + test-jsui.js + test-script2.js) is the most recent.

it leaks very slowly and crashes within an hour on my machine WITHOUT calling to gc().

My actual patch under development which is a much more complex UI using the actual version of script2.js bleeds to death within seconds (i.e. several calls to layout() method) without calling gc() and very-very slow (couple of megabytes per hour) when I do call gc() at the end of layout().

Since my patch will not call layout() this many times per session, I consider calling gc() an OK workaround. But I would like to pin down the leak eventually, because I use javascript / jsui a lot and eventually would want to use it in installations that run longer.


Viewing 10 posts - 1 through 10 (of 10 total)