<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><blockquote type="cite" class=""><div class="">On Mar 28, 2017, at 9:55 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="">Matt,<div class="">I tested this on Firefox and Chrome and saw that Chrome captures up to 200 frames. &nbsp;I don’t see Firefox capturing frames at all when not throwing an Error. &nbsp;Were you looking at Error.stack for Firefox when you came up with the 128 frames number? &nbsp;Maybe there’s a Firebug option I’m not familiar with?</div></div></div></blockquote><div><br class=""></div>The 128 frames is what I observed in Firefox’s console after loading a page which runs a script recursively in order to trigger a stack overflow. Enabling “Pause on Exceptions” in Firefox didn’t cause the debugger to pause when throwing the error (same as Chrome) so I’m not sure how to interact with the Error object.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Geoff,</div><div class="">It just occurred to me that the developer does have one recourse: he/she can use break on exception thrown / on uncaught exception, and inspect the full stack via the debugger.</div><div class=""><br class=""></div><div class="">Mark</div><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 28, 2017, at 9:08 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="">Currently, there’s no way for the developer to change this. &nbsp;We can certainly make it an option that the Inspector can change if desired.<div class=""><br class=""></div><div class="">Mark<br class=""><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 28, 2017, at 7:35 PM, Matt Baker &lt;<a href="mailto:matthew_a_baker@apple.com" class="">matthew_a_baker@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=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 28, 2017, at 4:23 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=""><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=""><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></div></blockquote><div class=""><br class=""></div><div class="">FireFox and Chrome show console entires with exception stack traces with 128 and 200 frames (respectively).</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div>Geoff<div class=""><br class=""><div class=""><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=""><a href="https://lists.webkit.org/mailman/listinfo/webkit-dev" class="">https://lists.webkit.org/mailman/listinfo/webkit-dev</a><br class=""></div></blockquote></div><br class=""></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><br class=""></div></blockquote></div><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><br class=""></div></blockquote></div><br class=""></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=""></body></html>