<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Does the separate exceptionStackTraceLimit mean that if a developer gets a truncated stack trace in the Web Inspector, there’s no way for the developer to remedy that? Is that what other browsers’ developer tools do?</div><div class=""><br class=""></div>Geoff<div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 28, 2017, at 4:09 PM, Mark Lam &lt;<a href="mailto:mark.lam@apple.com" class="">mark.lam@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">To follow up, I’ve implemented the change in r214289: &lt;<a href="http://trac.webkit/" class="">http://trac.webkit</a>.org/r214289&gt;. &nbsp;Error.stackTraceLimit is now 100. &nbsp;I also implemented a separate exceptionStackTraceLimit for stack traces captured at the time of throwing a value (not to be confused with Error.stack which is captured at the time of instantiation of the Error object). &nbsp;exceptionStackTraceLimit is also limited to 100 by default.<div class=""><br class=""></div><div class="">Mark</div><div class=""><br class=""><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 17, 2017, at 1:04 PM, Mark Lam &lt;<a href="mailto:mark.lam@apple.com" class="">mark.lam@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">@Geoff, my testing shows that we can do 200 frames and still perform well (~1 second to console.log Error.stack). &nbsp;Base on what we at present, I think 100 is a good round number to use as our default stackTraceLimit.</div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Mar 17, 2017, at 11:40 AM, Maciej Stachowiak &lt;<a href="mailto:mjs@apple.com" class="">mjs@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><br class="Apple-interchange-newline">On Mar 17, 2017, at 11:09 AM, Mark Lam &lt;<a href="mailto:mark.lam@apple.com" class="">mark.lam@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Thanks for the reminder to back observations up with data. &nbsp;I was previously running some tests that throws StackOverflowErrors a lot (which tainted my perspective), and I made a hasty conclusion which isn’t good. &nbsp;Anyway, here’s the data using an instrumented VM to take some measurements and a simple test program that recurses forever to throw a StackOverflowError (run on a MacPro):</div><div class=""><br class=""></div><div class="">1. For a release build of jsc shell:</div><div class="">&nbsp; &nbsp; Time to capture exception stack = 0.002807 sec<br class="">&nbsp; &nbsp;&nbsp;Number of stack frames captured = 31722<br class="">&nbsp; &nbsp;&nbsp;sizeof StackFrame = 24</div><div class="">&nbsp; &nbsp; total memory consumed = ~761328 bytes.</div><div class=""><br class=""></div><div class="">2. For a debug build of jsc shell:</div><div class="">&nbsp; &nbsp; Time to capture exception stack = 0.052107 sec<br class="">&nbsp; &nbsp;&nbsp;Number of stack frames captured = 31688<br class="">&nbsp; &nbsp;&nbsp;sizeof StackFrame = 24<br class=""><div class="">&nbsp; &nbsp; total memory consumed = ~760512 bytes.</div></div><div class=""><br class=""></div><div class="">So, regarding performance, I was wrong. &nbsp;The amount of time taken to capture the entire JS stack each time is insignificant.</div><div class="">Regarding memory usage, ~760K is not so good, but maybe it’s acceptable.</div><div class=""><br class=""></div><div class="">Comparing browsers with their respective inspectors open:</div><div class=""><br class=""></div><div class="">1. Chrome</div><div class="">&nbsp; &nbsp; number of frames captured: 10</div><div class="">&nbsp; &nbsp; length of e.stack string: 824 chars</div><div class="">&nbsp; &nbsp; time to&nbsp;console.log&nbsp;e.stack: 0.27 seconds</div><div class=""><br class=""></div><div class="">2. Firefox</div><div class="">&nbsp; &nbsp; number of frames captured: 129</div><div class="">&nbsp; &nbsp; length of e.stack string: 8831 chars</div><div class=""><div class="">&nbsp; &nbsp; time to&nbsp;console.log&nbsp;e.stack: 0.93 seconds</div></div><div class=""><br class=""></div><div class="">3. Safari</div><div class=""><div class="">&nbsp; &nbsp; number of frames captured: 31722</div><div class="">&nbsp; &nbsp; length of e.stack string: 218821 chars</div></div><div class=""><div class="">&nbsp; &nbsp; time to console.log e.stack: 50.8 seconds</div></div><div class=""><br class=""></div><div class="">4. Safari (with error.stack shrunk to 201 frames at time of capture to simulate my proposal)</div><div class=""><div class="">&nbsp; &nbsp; number of frames captured: 201</div><div class="">&nbsp; &nbsp; length of e.stack string: 13868 chars</div></div><div class="">&nbsp; &nbsp; time to console.log e.stack: 1 second</div><div class=""><div class=""><br class=""></div></div><div class="">With my proposal, the experience of printing Error.stack drops from 50.8 seconds to about 1 second. &nbsp;The memory used for capturing the stack also drops from ~760K to 5K.</div><div class=""><br class=""></div><div class="">I wasn’t aware of the Error.stackTraceLimit, but that does sound like a better solution than my proposal since it gives developers the ability to capture more stack frames if they need it. &nbsp;Chrome’s default Error.stackTraceLimit appears to be 10. &nbsp;MS appears to support it as well and defaults to 10 (<a href="https://docs.microsoft.com/en-us/scripting/javascript/reference/stacktracelimit-property-error-javascript" class="">https://docs.microsoft.com/en-us/scripting/javascript/reference/stacktracelimit-property-error-javascript</a>). &nbsp;Firefox does now.</div></div></div></blockquote><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Out of curiosity: Why does Firefox capture 129 frames instead of 31722 in this case? Do they have a hardcoded limit?</div></div></blockquote><div class=""><br class=""></div><div class="">Actually, my previous frame counts are a bit off. &nbsp;I was using e.stack.split(/\r\n|\r|\n/).length as the frame count. &nbsp;Below, I just copy the console.log dump into an editor and take the line count from there as the frame count instead. &nbsp;The result of that string.split appears to be a bit off from the actual frames printed by console.log.&nbsp;</div><div class=""><br class=""></div><div class="">I also modified my recursing test function to console.log the re-entry count on entry and this is what I saw:</div><div class=""><br class=""></div><div class="">1. Chrome</div><div class="">&nbsp; &nbsp; test reported reentry count = 10150</div><div class="">&nbsp; &nbsp; ....split(…).length = 11 (because Chromes starts e.stack with a line "RangeError: Maximum call stack size exceeded”)</div><div class="">&nbsp; &nbsp; e.stack lines according to editor = 10 frames</div><div class=""><br class=""></div><div class="">2. Firefox</div><div class="">&nbsp; &nbsp;&nbsp;test reported reentry&nbsp;count =&nbsp;222044</div><div class="">&nbsp; &nbsp; ....split(…).length = 129 (probably because there’s an extra newline in there somewhere)</div><div class="">&nbsp; &nbsp;&nbsp;e.stack lines according to editor = 128 frames</div><div class=""><br class=""></div><div class="">3. Safari</div><div class="">&nbsp; &nbsp;&nbsp;test reported reentry&nbsp;count =&nbsp;31701</div><div class="">&nbsp; &nbsp; ....split(…).length = 31722 (I don’t know why there’s a 21 frame discrepancy here. &nbsp;I’ll debug this later)</div><div class="">&nbsp; &nbsp;&nbsp;e.stack lines according to editor = ??? frames (WebInspector hangs every time I try to scroll in it, let alone let me highlight and copy the stack trace. &nbsp;So I gave up)</div><div class=""><br class=""></div><div class="">Assuming the test function frame is not significantly different in size for all browsers, it looks like:</div><div class="">1. Chrome uses a much smaller stack (about 1/3 of our stack).</div><div class="">2. Firefox uses a much larger stack (possibly the full machine stack), but caps its Error.stack to just 128 frames (possibly a hardcoded limit).</div><div class=""><br class=""></div><div class="">Mark</div><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">&nbsp;- Maciej</div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div><div class="">Does anyone object to us adopting Error.stackTraceLimit and setting the default to 10 to match Chrome?</div><div class=""><br class=""></div><div class="">Mark<br class=""><br class=""><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 16, 2017, at 11:29 PM, Geoffrey Garen &lt;<a href="mailto:ggaren@apple.com" class="">ggaren@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Can you be more specific about the motivation here?<br class=""><br class="">Do we have any motivating examples that will tell us wether time+memory were unacceptable before this change, or are acceptable after this change?<br class=""><br class="">In our motivating examples, does Safari use more time+memory than other browsers? If so, how large of a stack do other browsers capture?<br class=""><br class="">We already limit the size of the JavaScript stack to avoid performance problems like the ones you mention in many other contexts. Why is that limit not sufficient?<br class=""><br class="">Did you consider implementing Chrome’s Error.stackTraceLimit behavior?<br class=""><br class="">Geoff<br class=""><br class=""><blockquote type="cite" class="">On Mar 16, 2017, at 10:09 PM, Mark Lam &lt;<a href="mailto:mark.lam@apple.com" class="">mark.lam@apple.com</a>&gt; wrote:<br class=""><br class="">Hi folks,<br class=""><br class="">Currently, if we have an exception stack that is incredibly deep (especially for a StackOverflowError), JSC may end up thrashing memory just to capture the large stack trace in memory. &nbsp;&nbsp;&nbsp;This is bad for many reasons:<br class=""><br class="">1. the captured stack will take a lot of memory.<br class="">2. capturing the stack may take a long time (due to memory thrashing) and makes for a bad user experience.<br class="">3. if memory availability is low, capturing such a large stack may result in an OutOfMemoryError being thrown in its place.<br class="">&nbsp;&nbsp;The OutOfMemoryError thrown there will also have the same problem with capturing such a large stack.<br class="">4. most of the time, no one will look at the captured Error.stack anyway.<br class=""><br class="">Since there isn’t a standard on what we really need to capture for Error.stack, I propose that we limit how much stack we capture to a practical size. &nbsp;How about an Error.stack that consists of (1) the top N frames, (2) an ellipses, and (3) the bottom M frames? &nbsp;If the number of frames on the stack at the time of capture &nbsp;is less or equal to than N + M frames, then Error.stack will just show the whole stack with no ellipses. &nbsp;For example, if N is 4 and M is 2, the captured stack will look something like this:<br class=""><br class="">&nbsp;&nbsp;&nbsp;&nbsp;foo10001<br class="">&nbsp;&nbsp;&nbsp;&nbsp;foo10000<br class="">&nbsp;&nbsp;&nbsp;&nbsp;foo9999<br class="">&nbsp;&nbsp;&nbsp;&nbsp;foo9998<br class="">&nbsp;&nbsp;&nbsp;&nbsp;…<br class="">&nbsp;&nbsp;&nbsp;&nbsp;foo1<br class="">&nbsp;&nbsp;&nbsp;&nbsp;foo0<br class=""><br class="">If we pick a sufficient large number for N and M (I suggest 100 each), I think this should provide sufficient context for debugging uses of Error.stack, while keeping an upper bound on how much memory and time we throw at capturing the exception stack.<br class=""><br class="">My plan for implementing this is:<br class="">1. change Exception::finishCreation() to only capture the N and M frames, plus possibly 1 ellipses placeholder in the between them.<br class="">2. change all clients of Exception::stack() to be able to recognize and render the ellipses.<br class=""><br class="">Does anyone object to doing this or have a compelling reason why this should not be done?<br class=""><br class="">Thanks.<br class=""><br class="">Mark<br class=""><br class=""><br class=""><br class="">_______________________________________________<br class="">webkit-dev mailing list<br class=""><a href="mailto:webkit-dev@lists.webkit.org" class="">webkit-dev@lists.webkit.org</a><br class=""><a href="https://lists.webkit.org/mailman/listinfo/webkit-dev" class="">https://lists.webkit.org/mailman/listinfo/webkit-dev</a><br class=""></blockquote><br class=""></div></div></blockquote></div><br class=""></div></div></div>_______________________________________________<br class="">webkit-dev mailing list<br class=""><a href="mailto:webkit-dev@lists.webkit.org" class="">webkit-dev@lists.webkit.org</a><br class=""><a href="https://lists.webkit.org/mailman/listinfo/webkit-dev" class="">https://lists.webkit.org/mailman/listinfo/webkit-dev</a></div></blockquote></div></blockquote></div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">webkit-dev mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:webkit-dev@lists.webkit.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">webkit-dev@lists.webkit.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.webkit.org/mailman/listinfo/webkit-dev" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://lists.webkit.org/mailman/listinfo/webkit-dev</a></div></blockquote></div><br class=""></div></div></div>_______________________________________________<br class="">webkit-dev mailing list<br class=""><a href="mailto:webkit-dev@lists.webkit.org" class="">webkit-dev@lists.webkit.org</a><br class="">https://lists.webkit.org/mailman/listinfo/webkit-dev<br class=""></div></blockquote></div><br class=""></div></body></html>