[cc-ing Lou. We need to improve the documentation on the Debugger
memory tools. I thought I had written something, but I can't seem to
find it, and the current doc
http://www.openlaszlo.org/lps4/docs/developers/debugging.html#d0e121455
is confusing even to me. I've attached some additional info to the
end of this message.]
On 2008-04-09, at 11:27 EDT, Gilad Parann-Nissany wrote:
Hi
We're trying to optimize our memory usage, not exactly find leaks
but profile our memory. We are on OL 4.0.8.
So far we've used _LzDebug.whyAlive() to analyze an application; is
there a different recommended way to analyze the memory allcoation
of an OL app? or are we doing the right thing?
That's the best tool we have for fine-grained analysis. I also use
the operating system's memory profile tools to see if my application
is growing without bound, although this is a very 'noisy' measure,
because all you can look at is the total memory of the browser. If
you are _only_ running your application in the browser, it is quite
likely that any fluctuation in memory usage is due to your
application, but also note that most runtimes will only garbage
collect when your application is idle. Sometimes minimizing the
browser window will trigger a garbage collection.
Attached a screenshot of an example run. We need help to understand
this output:
• what are smoots?
An small (inside) joke: http://en.wikipedia.org/wiki/Smoot
• why do objects contain smoots?
Since the memory leak detector is running in the SWF or DHTML virtual
machine, it has no way to actually measure the size of an object in
bytes. It approximates the size of an object by counting the objects
properties, and by assuming some reasonable defaults for built-in
objects like numbers and strings. Smoots should be proportional to
bytes, but they are not bytes.
• what are the numbers that start with a pound-sterling sign? in
regular paranthesis like Array(4)? with "#" like in Array(4) #262
This is intended to represent the 'total weight' of the object. It is
the sum of the object's smoots and the smoots of it's children and
it's children's children, etc.
• how to interpret the names on the leftmost side such as
global.spriteroot? the ones after the colon?
This is the shortest path from the root to the object, the most likely
reason the object is still 'alive'. (There may be other links to the
object, but the tool only records the shortest one.)
is there any way we can translate these into bytes of memory? we
have measured total RAM used separately, but would like to know
whether the result of whyAlive is a dependable measure of the
breakdown of this memory...
As above, smoots should be proportional to total memory.
---
[Additional info]
As of 4.0.8, there are some fixes for the leak detection tools. The
leak detector no longer gets fooled by getters in the runtime that
return a new object each time you access a property. You no longer
have to go through hoops to get the output of `Debug.whyAlive()` -- it
prints out a useful summary again, and if you inspect the result, you
get the full report. Each element in the leak report is also
inspectable. Ex.:
lzx> Debug.markObjects()
Marking objects ...
lzx> DEBUG: 7 loops @ 1379 iterations, 1137.97 milliseconds
... done!
lzx> Debug.findNewObjects()
Finding new objects ...
lzx> DEBUG: 7 loops @ 1379 iterations, 1153.63 milliseconds
... done!
lzx> Debug.whyAlive()
82 smoots [4 objects @ ~21 smoots each]:
global.spriteroot.$m1.debugloader.loadmc1.reqobj: (£54) «Object#138|
{_dbg_check: 54, _dbg_smoots...»
global._componentmanager.service.upkeydel: (£20) «LzDelegate#141|
«lz._componentmanager».d...»
global.LzKeys.downKeysArray: (£8) «Array(2)#144| [16, 68]»
.: (£0) «¿movieclip?»
«__LzLeaks(4)#136| 82 smoots [4 objects @ ~21 smoots each]»
lzx> Debug.inspect(82 smoots [4 objects @ ~21 smoots each])
«__LzLeaks(4)#136| 82 smoots [4 objects @ ~21 smoots each]» {
constructor: __LzLeaks
length: 4
0: global.spriteroot.
$m1.debugloader.loadmc1.reqobj: (£54) «Object#138| {_dbg_check: 54,
_dbg_smoots...»
1: global._componentmanager.service.upkeydel:
(£20) «LzDelegate#141| «lz._componentmanager».d...»
2: global.LzKeys.downKeysArray: (£8)
«Array(2)#144| [16, 68]»
3: .: (£0) «¿movieclip?»
}«__LzLeaks(4)#136| 82 smoots [4 objects @ ~21 smoots each]»
lzx> Debug.inspect(«__LzLeak| global.LzKeys.downKeysArray: (...»)
«__LzLeak#151| global.LzKeys.downKeysArray: (£8) «Array(2)#144| [16,
68]»» {
constructor: __LzLeak
leaked: 8
obj: (£8) [16, 68]
parent: #LzKeys
path: 'global.LzKeys'
property: 'downKeysArray'
}«__LzLeak#151| global.LzKeys.downKeysArray: (£8) «Array(2)#144|
[16, 68]»»
This shows inspecting the memory report '__LzLeaks', which has four
leaks reported, and then inspecting an individual leak report
'__LzLeak', which has the amount 'leaked', the 'obj'ect that the
report is about, the 'parent' of that object (the object that is
referencing the reported object, the 'path' from the root to the
parent, and the 'property' of the parent that contains the reported
object.
Hope this is helpful. Let me know if there are further questions.