Matt,
I tested this on Firefox and Chrome and saw that Chrome captures up to 200 
frames.  I don’t see Firefox capturing frames at all when not throwing an 
Error.  Were you looking at Error.stack for Firefox when you came up with the 
128 frames number?  Maybe there’s a Firebug option I’m not familiar with?

Geoff,
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.

Mark


> On Mar 28, 2017, at 9:08 PM, Mark Lam <mark....@apple.com> wrote:
> 
> Currently, there’s no way for the developer to change this.  We can certainly 
> make it an option that the Inspector can change if desired.
> 
> Mark
> 
> 
>> On Mar 28, 2017, at 7:35 PM, Matt Baker <matthew_a_ba...@apple.com 
>> <mailto:matthew_a_ba...@apple.com>> wrote:
>> 
>>> On Mar 28, 2017, at 4:23 PM, Geoffrey Garen <gga...@apple.com 
>>> <mailto:gga...@apple.com>> wrote:
>>> 
>>> 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?
>> 
>> FireFox and Chrome show console entires with exception stack traces with 128 
>> and 200 frames (respectively).
>> 
>>> 
>>> Geoff
>>> 
>>>> On Mar 28, 2017, at 4:09 PM, Mark Lam <mark....@apple.com 
>>>> <mailto:mark....@apple.com>> wrote:
>>>> 
>>>> To follow up, I’ve implemented the change in r214289: <http://trac.webkit 
>>>> <http://trac.webkit/>.org/r214289>.  Error.stackTraceLimit is now 100.  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).  exceptionStackTraceLimit is also limited to 100 by default.
>>>> 
>>>> Mark
>>>> 
>>>> 
>>>>> On Mar 17, 2017, at 1:04 PM, Mark Lam <mark....@apple.com 
>>>>> <mailto:mark....@apple.com>> wrote:
>>>>> 
>>>>> @Geoff, my testing shows that we can do 200 frames and still perform well 
>>>>> (~1 second to console.log Error.stack).  Base on what we at present, I 
>>>>> think 100 is a good round number to use as our default stackTraceLimit.
>>>>> 
>>>>>> On Mar 17, 2017, at 11:40 AM, Maciej Stachowiak <m...@apple.com 
>>>>>> <mailto:m...@apple.com>> wrote:
>>>>>> 
>>>>>>> 
>>>>>>> On Mar 17, 2017, at 11:09 AM, Mark Lam <mark....@apple.com 
>>>>>>> <mailto:mark....@apple.com>> wrote:
>>>>>>> 
>>>>>>> Thanks for the reminder to back observations up with data.  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.  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):
>>>>>>> 
>>>>>>> 1. For a release build of jsc shell:
>>>>>>>     Time to capture exception stack = 0.002807 sec
>>>>>>>     Number of stack frames captured = 31722
>>>>>>>     sizeof StackFrame = 24
>>>>>>>     total memory consumed = ~761328 bytes.
>>>>>>> 
>>>>>>> 2. For a debug build of jsc shell:
>>>>>>>     Time to capture exception stack = 0.052107 sec
>>>>>>>     Number of stack frames captured = 31688
>>>>>>>     sizeof StackFrame = 24
>>>>>>>     total memory consumed = ~760512 bytes.
>>>>>>> 
>>>>>>> So, regarding performance, I was wrong.  The amount of time taken to 
>>>>>>> capture the entire JS stack each time is insignificant.
>>>>>>> Regarding memory usage, ~760K is not so good, but maybe it’s acceptable.
>>>>>>> 
>>>>>>> Comparing browsers with their respective inspectors open:
>>>>>>> 
>>>>>>> 1. Chrome
>>>>>>>     number of frames captured: 10
>>>>>>>     length of e.stack string: 824 chars
>>>>>>>     time to console.log e.stack: 0.27 seconds
>>>>>>> 
>>>>>>> 2. Firefox
>>>>>>>     number of frames captured: 129
>>>>>>>     length of e.stack string: 8831 chars
>>>>>>>     time to console.log e.stack: 0.93 seconds
>>>>>>> 
>>>>>>> 3. Safari
>>>>>>>     number of frames captured: 31722
>>>>>>>     length of e.stack string: 218821 chars
>>>>>>>     time to console.log e.stack: 50.8 seconds
>>>>>>> 
>>>>>>> 4. Safari (with error.stack shrunk to 201 frames at time of capture to 
>>>>>>> simulate my proposal)
>>>>>>>     number of frames captured: 201
>>>>>>>     length of e.stack string: 13868 chars
>>>>>>>     time to console.log e.stack: 1 second
>>>>>>> 
>>>>>>> With my proposal, the experience of printing Error.stack drops from 
>>>>>>> 50.8 seconds to about 1 second.  The memory used for capturing the 
>>>>>>> stack also drops from ~760K to 5K.
>>>>>>> 
>>>>>>> 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.  Chrome’s default 
>>>>>>> Error.stackTraceLimit appears to be 10.  MS appears to support it as 
>>>>>>> well and defaults to 10 
>>>>>>> (https://docs.microsoft.com/en-us/scripting/javascript/reference/stacktracelimit-property-error-javascript
>>>>>>>  
>>>>>>> <https://docs.microsoft.com/en-us/scripting/javascript/reference/stacktracelimit-property-error-javascript>).
>>>>>>>   Firefox does now.
>>>>>> 
>>>>>> Out of curiosity: Why does Firefox capture 129 frames instead of 31722 
>>>>>> in this case? Do they have a hardcoded limit?
>>>>> 
>>>>> Actually, my previous frame counts are a bit off.  I was using 
>>>>> e.stack.split(/\r\n|\r|\n/).length as the frame count.  Below, I just 
>>>>> copy the console.log dump into an editor and take the line count from 
>>>>> there as the frame count instead.  The result of that string.split 
>>>>> appears to be a bit off from the actual frames printed by console.log. 
>>>>> 
>>>>> I also modified my recursing test function to console.log the re-entry 
>>>>> count on entry and this is what I saw:
>>>>> 
>>>>> 1. Chrome
>>>>>     test reported reentry count = 10150
>>>>>     ....split(…).length = 11 (because Chromes starts e.stack with a line 
>>>>> "RangeError: Maximum call stack size exceeded”)
>>>>>     e.stack lines according to editor = 10 frames
>>>>> 
>>>>> 2. Firefox
>>>>>     test reported reentry count = 222044
>>>>>     ....split(…).length = 129 (probably because there’s an extra newline 
>>>>> in there somewhere)
>>>>>     e.stack lines according to editor = 128 frames
>>>>> 
>>>>> 3. Safari
>>>>>     test reported reentry count = 31701
>>>>>     ....split(…).length = 31722 (I don’t know why there’s a 21 frame 
>>>>> discrepancy here.  I’ll debug this later)
>>>>>     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.  So I gave up)
>>>>> 
>>>>> Assuming the test function frame is not significantly different in size 
>>>>> for all browsers, it looks like:
>>>>> 1. Chrome uses a much smaller stack (about 1/3 of our stack).
>>>>> 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).
>>>>> 
>>>>> Mark
>>>>> 
>>>>> 
>>>>>> 
>>>>>>  - Maciej
>>>>>> 
>>>>>>> 
>>>>>>> Does anyone object to us adopting Error.stackTraceLimit and setting the 
>>>>>>> default to 10 to match Chrome?
>>>>>>> 
>>>>>>> Mark
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>> On Mar 16, 2017, at 11:29 PM, Geoffrey Garen <gga...@apple.com 
>>>>>>>> <mailto:gga...@apple.com>> wrote:
>>>>>>>> 
>>>>>>>> Can you be more specific about the motivation here?
>>>>>>>> 
>>>>>>>> Do we have any motivating examples that will tell us wether 
>>>>>>>> time+memory were unacceptable before this change, or are acceptable 
>>>>>>>> after this change?
>>>>>>>> 
>>>>>>>> In our motivating examples, does Safari use more time+memory than 
>>>>>>>> other browsers? If so, how large of a stack do other browsers capture?
>>>>>>>> 
>>>>>>>> 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?
>>>>>>>> 
>>>>>>>> Did you consider implementing Chrome’s Error.stackTraceLimit behavior?
>>>>>>>> 
>>>>>>>> Geoff
>>>>>>>> 
>>>>>>>>> On Mar 16, 2017, at 10:09 PM, Mark Lam <mark....@apple.com 
>>>>>>>>> <mailto:mark....@apple.com>> wrote:
>>>>>>>>> 
>>>>>>>>> Hi folks,
>>>>>>>>> 
>>>>>>>>> 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.    This is 
>>>>>>>>> bad for many reasons:
>>>>>>>>> 
>>>>>>>>> 1. the captured stack will take a lot of memory.
>>>>>>>>> 2. capturing the stack may take a long time (due to memory thrashing) 
>>>>>>>>> and makes for a bad user experience.
>>>>>>>>> 3. if memory availability is low, capturing such a large stack may 
>>>>>>>>> result in an OutOfMemoryError being thrown in its place.
>>>>>>>>>   The OutOfMemoryError thrown there will also have the same problem 
>>>>>>>>> with capturing such a large stack.
>>>>>>>>> 4. most of the time, no one will look at the captured Error.stack 
>>>>>>>>> anyway.
>>>>>>>>> 
>>>>>>>>> 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.  How about an Error.stack that consists of (1) the 
>>>>>>>>> top N frames, (2) an ellipses, and (3) the bottom M frames?  If the 
>>>>>>>>> number of frames on the stack at the time of capture  is less or 
>>>>>>>>> equal to than N + M frames, then Error.stack will just show the whole 
>>>>>>>>> stack with no ellipses.  For example, if N is 4 and M is 2, the 
>>>>>>>>> captured stack will look something like this:
>>>>>>>>> 
>>>>>>>>>     foo10001
>>>>>>>>>     foo10000
>>>>>>>>>     foo9999
>>>>>>>>>     foo9998
>>>>>>>>>     …
>>>>>>>>>     foo1
>>>>>>>>>     foo0
>>>>>>>>> 
>>>>>>>>> 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.
>>>>>>>>> 
>>>>>>>>> My plan for implementing this is:
>>>>>>>>> 1. change Exception::finishCreation() to only capture the N and M 
>>>>>>>>> frames, plus possibly 1 ellipses placeholder in the between them.
>>>>>>>>> 2. change all clients of Exception::stack() to be able to recognize 
>>>>>>>>> and render the ellipses.
>>>>>>>>> 
>>>>>>>>> Does anyone object to doing this or have a compelling reason why this 
>>>>>>>>> should not be done?
>>>>>>>>> 
>>>>>>>>> Thanks.
>>>>>>>>> 
>>>>>>>>> Mark
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> _______________________________________________
>>>>>>>>> webkit-dev mailing list
>>>>>>>>> webkit-dev@lists.webkit.org <mailto:webkit-dev@lists.webkit.org>
>>>>>>>>> https://lists.webkit.org/mailman/listinfo/webkit-dev 
>>>>>>>>> <https://lists.webkit.org/mailman/listinfo/webkit-dev>
>>>>>>>> 
>>>>>>> 
>>>>>>> _______________________________________________
>>>>>>> webkit-dev mailing list
>>>>>>> webkit-dev@lists.webkit.org <mailto:webkit-dev@lists.webkit.org>
>>>>>>> https://lists.webkit.org/mailman/listinfo/webkit-dev 
>>>>>>> <https://lists.webkit.org/mailman/listinfo/webkit-dev>
>>>>> _______________________________________________
>>>>> webkit-dev mailing list
>>>>> webkit-dev@lists.webkit.org <mailto:webkit-dev@lists.webkit.org>
>>>>> https://lists.webkit.org/mailman/listinfo/webkit-dev 
>>>>> <https://lists.webkit.org/mailman/listinfo/webkit-dev>
>>>> _______________________________________________
>>>> webkit-dev mailing list
>>>> webkit-dev@lists.webkit.org <mailto:webkit-dev@lists.webkit.org>
>>>> https://lists.webkit.org/mailman/listinfo/webkit-dev 
>>>> <https://lists.webkit.org/mailman/listinfo/webkit-dev>
>>> 
>>> _______________________________________________
>>> webkit-dev mailing list
>>> webkit-dev@lists.webkit.org <mailto:webkit-dev@lists.webkit.org>
>>> https://lists.webkit.org/mailman/listinfo/webkit-dev 
>>> <https://lists.webkit.org/mailman/listinfo/webkit-dev>
>> 
> 
> _______________________________________________
> webkit-dev mailing list
> webkit-dev@lists.webkit.org
> https://lists.webkit.org/mailman/listinfo/webkit-dev

_______________________________________________
webkit-dev mailing list
webkit-dev@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-dev

Reply via email to