Closed Bug 86355 Opened 24 years ago Closed 23 years ago

[FIX]Mozilla hangs (100% cpu) when doing view source (bidi page)

Categories

(Core :: Layout: Text and Fonts, defect, P2)

defect

Tracking

()

RESOLVED FIXED
mozilla0.9.9

People

(Reporter: ibalaban, Assigned: bzbarsky)

References

()

Details

(Keywords: hang, perf, topperf)

Attachments

(4 files, 1 obsolete file)

Reporter: Please read http://www.mozilla.org/quality/bug-writing-guidelines.html and use in the future http://www.mozilla.org/quality/help/bug-form.html t file a new bug. win2k build 20010617.. (CVS opt) Ok I get a hang if I do this : Load that URL. (this page use java, but the java applet is empty for me) Open view source - hang
Status: UNCONFIRMED → NEW
Ever confirmed: true
Keywords: hang
Disabling view-source syntax highlighting would solve this problem. I remember there's a coloring-the-bad-HTML-code-causing-hang bug filed already.
Whiteboard: DUPEME
over to XPApps GUI Features for triage.
Assignee: asa → blake
Component: Browser-General → XP Apps: GUI Features
QA Contact: doronr → sairuh
dup *** This bug has been marked as a duplicate of 81531 ***
Status: NEW → RESOLVED
Closed: 24 years ago
Resolution: --- → DUPLICATE
Whiteboard: DUPEME
reopening ...
Status: RESOLVED → REOPENED
Component: XP Apps: GUI Features → BiDi Hebrew & Arabic
Resolution: DUPLICATE → ---
Yes, turning off the 'syntax coloring' for view-source does alleviate the 'hang' when viewing the source of this page (and it is a known problem that syntax coloring is not fast). However, I repetitively broke in the debugger (win2k) while this was churning, and every single time it was with this stack trace below, iterating through a list of frames. Reassigning to Bidi for consideration/analysis. nsBidiPresUtils::RemoveBidiContinuation(const nsBidiPresUtils * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsIPresContext * 0x036c60f8, nsIFrame * 0x0373fb40, nsIFrame * 0x00000000, nsIContent * 0x036a2860, int & 5346, int & 27) line 785 + 22 bytes nsBidiPresUtils::Resolve(nsBidiPresUtils * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsIPresContext * 0x036c60f8, nsIFrame * 0x0000001a, nsIFrame * 0x005b9278, int & 0) line 317 + 25 bytes nsBlockFrame::Reflow(nsBlockFrame * const 0x00000001, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0) line 704 nsBlockReflowContext::DoReflowBlock(nsBlockReflowContext * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsHTMLReflowState & {...}, nsReflowReason eReflowReason_Initial, nsIFrame * 0x035b917c, const nsRect & {...}, int 1239056, int 0, int 1239040, nsMargin & {...}, unsigned int & 0) line 573 nsBlockReflowContext::ReflowBlock(nsBlockReflowContext * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsIFrame * 0x00000002, const nsRect & {...}, int 0, int 0, int 1, nsMargin & {...}, unsigned int & 0) line 340 + 34 bytes nsBlockFrame::ReflowBlockFrame(nsBlockFrame * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBlockReflowState & {...}, nsLineBox * 0x00000000, int * 0x0012e99c) line 2960 nsBlockFrame::ReflowLine(nsBlockFrame * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBlockReflowState & {...}, nsLineBox * 0x036fd0c8, int * 0x0012e99c, int 1) line 2223 nsBlockFrame::ReflowDirtyLines(nsBlockFrame * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBlockReflowState & {...}) line 2027 nsBlockFrame::Reflow(nsBlockFrame * const 0x00000000, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0) line 795 nsBlockReflowContext::DoReflowBlock(nsBlockReflowContext * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsHTMLReflowState & {...}, nsReflowReason eReflowReason_Incremental, nsIFrame * 0x035b6cdc, const nsRect & {...}, int 1240812, int 120, int 1240796, nsMargin & {...}, unsigned int & 0) line 573 nsBlockReflowContext::ReflowBlock(nsBlockReflowContext * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsIFrame * 0x00000002, const nsRect & {...}, int 1, int 0, int 1, nsMargin & {...}, unsigned int & 0) line 340 + 34 bytes nsBlockFrame::ReflowBlockFrame(nsBlockFrame * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBlockReflowState & {...}, nsLineBox * 0x00000078, int * 0x0012f078) line 2960 nsBlockFrame::ReflowLine(nsBlockFrame * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBlockReflowState & {...}, nsLineBox * 0x035b6d64, int * 0x0012f078, int 1) line 2223 nsBlockFrame::ReflowDirtyLines(nsBlockFrame * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBlockReflowState & {...}) line 2027 nsBlockFrame::Reflow(nsBlockFrame * const 0x00000000, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0) line 795 nsContainerFrame::ReflowChild(nsContainerFrame * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsIFrame * 0x035b6aac, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, int 0, int 0, unsigned int 0, unsigned int & 0) line 747 CanvasFrame::Reflow(CanvasFrame * const 0x0368c970, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0) line 579 nsBoxToBlockAdaptor::Reflow(nsBoxToBlockAdaptor * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBoxLayoutState & {...}, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0, int 0, int 0, int 9480, int 6450, int 1) line 869 nsBoxToBlockAdaptor::DoLayout(nsBoxToBlockAdaptor * const 0x00000000, nsBoxLayoutState & {...}) line 523 + 40 bytes nsBox::Layout(nsBox * const 0x035b69b8, nsBoxLayoutState & {...}) line 985 nsScrollBoxFrame::DoLayout(nsScrollBoxFrame * const 0x00000005, nsBoxLayoutState & {...}) line 379 nsBox::Layout(nsBox * const 0x0368cd14, nsBoxLayoutState & {...}) line 985 nsContainerBox::LayoutChildAt(nsBoxLayoutState & {...}, nsIBox * 0x00000000, const nsRect & {...}) line 591 + 9 bytes nsGfxScrollFrameInner::LayoutBox(nsGfxScrollFrameInner * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBoxLayoutState & {...}, nsIBox * 0x0368cd14, const nsRect & {...}) line 1037 + 17 bytes nsGfxScrollFrameInner::Layout(nsGfxScrollFrameInner * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsBoxLayoutState & {...}) line 1150 nsGfxScrollFrame::DoLayout(nsGfxScrollFrame * const 0x0368caac, nsBoxLayoutState & {...}) line 1047 nsBox::Layout(nsBox * const 0x0368caac, nsBoxLayoutState & {...}) line 985 nsBoxFrame::Reflow(nsBoxFrame * const 0x0368ca78, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0) line 781 nsGfxScrollFrame::Reflow(nsGfxScrollFrame * const 0x0368ca78, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0) line 738 nsContainerFrame::ReflowChild(nsContainerFrame * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsIFrame * 0x0368ca78, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, int 0, int 0, unsigned int 0, unsigned int & 0) line 747 ViewportFrame::Reflow(ViewportFrame * const 0x0368c938, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsHTMLReflowState & {...}, unsigned int & 0) line 538 nsHTMLReflowCommand::Dispatch(nsHTMLReflowCommand * const 0x036d21b0, nsIPresContext * 0x036c60f8, nsHTMLReflowMetrics & {...}, const nsSize & {...}, nsIRenderingContext & {...}) line 145 PresShell::ProcessReflowCommand(PresShell * const 0x01e644a0 const nsDirectionalFrame::`vftable', nsVoidArray & {...}, int 1, nsHTMLReflowMetrics & {...}, nsSize & {...}, nsIRenderingContext & {...}) line 5717 PresShell::ProcessReflowCommands(PresShell * const 0x01e644a0 const nsDirectionalFrame::`vftable', int 1) line 5772 ReflowEvent::HandleEvent(ReflowEvent * const 0x01e644a0 const nsDirectionalFrame::`vftable') line 5630 PL_HandleEvent(PLEvent * 0x036fd2b8) line 591 PL_ProcessPendingEvents(PLEventQueue * 0x1002aa70) line 520 + 6 bytes _md_EventReceiverProc(HWND__ * 0x00ced528, unsigned int 4200147, unsigned int 12859920, long 0) line 1071 + 10 bytes nsAppShellService::Run(nsAppShellService * const 0x00c43a10) line 418 main1(int 1, char * * 0x00322db0, nsISupports * 0x00324210) line 1139 + 9 bytes main(int 1, char * * 0x00322db0) line 1437 + 25 bytes WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00400000, char * 0x00133226, HINSTANCE__ * 0x00400000) line 1455 + 21 bytes MOZILLA! WinMainCRTStartup + 308 bytes KERNEL32! 77e87903()
Assignee: blake → mkaply
Status: REOPENED → NEW
QA Contact: sairuh → giladehven
tweak summary.
Summary: Mozilla hangs (100% cpu) when woken up → Mozilla hangs (100% cpu) when doing view source (bidi page)
I have been looking into this. All the <span>s in the source with the syntax higlighting make the bidi resolution very involved, especially since the whole source is one huge block frame. We should find a way to bypass all that processing, maybe by letting the code that outputs the source do its own bidi reordering in advance.
simon- isn't it true that it is possible for peopel to write a html just like what the view source process generated ? View Source is simply a filter which transform one html to another html. Do we have some flaw in our bidi processing which cause infinite loop?
Mass-move all BiDi Hebrew and Arabic qa to me, zach@zachlipton.com. Thank you Gilad for your service to this component, and best of luck to you in the future. Sholom.
QA Contact: giladehven → zach
win98 Mozilla build ID: 2001091703 , syntax coloring turned off: Attempting to view a source of a Hebrew page hangs the "view source" window, but not the rest of Netscape. Viewing English pages works fine.
*** Bug 103600 has been marked as a duplicate of this bug. ***
I just did a profile of view source on this page (no hang, just took a bit). The result was definitely pointing at bidi as the main perf hog. About 60% of the time was spent in (not under, but _in_) nsBidiPresUtils::RemoveBidiContinuation. About 83% of the total hits were in nsBidiPresUtils::Resolve. So do we have any traction here? You say that view source being a single block frame makes this slow. There is currently a proposal to split up the single <pre> into multiple <pre> elements (splitting every 500 tokens or so, but only on newline tokens). Would that help the situation here? Anything else we can do?
Keywords: perf, topperf
Blocks: 84707
I'd also like to reiterate Frank's comments. In my mind, view source is the perfect "big text document with lots of markup" testcase. If we can improve performance here, chances are we also improve performance on bidi pages across the board.
>If we can improve performance here, chances are we also improve performance on >bidi pages across the board. I can't argue with that, but let me stress that view source is very untypical of bidi documents. A typical document will tend to have runs of text predominately in one direction interspersed with occasional (usually short) runs in the other direction, so |runCount|, which determines the number of iterations in |nsBidiPresUtils::Resolve| is typically quite small (10 would be unusually large). In view source on the other hand, |runCount| can easily run into 3 or 4 figures, which is why we get stuck in |nsBidiPresUtils::Resolve| for such a long time. Obviously anything we can do to improve performance inside the main for loop there will help a lot for view source, but may not be a significant win in other contexts. I will experiment with turning on the DUMP_TO_FILE option in nsViewSourceHTML.cpp and reformatting the output file to see the effect of splitting it into multiple <pre> elements. By the way, you can get good realworld examples of largish bidi pages with lots of markup by setting preferences at www.google.com to Interface Language: Hebrew and Number of Results: 100
Comparing pageload of attachment 58061 [details] and attachment 58062 [details], it looks as if increasing the number of <pre> elements will do wonders for this bug. I'm seeing about a 300% improvement.
Depends on: 114420
No longer depends on: 114420
Blocks: 115713
Win 2000, Mozilla 2002010303: URL: http://www.scan.co.uk/allprice.htm Viewing page source with syntax highlight takes long time to show it (and "eats" CPU power) even on Pentium4/1.5 GHz. Syntax highlight off, and everything is ok. Other interesting behaviour is that when the source is rendered mouse pointer is "jumping" instead of smooth moving, but... when the source is scrolled to the bottom - mouse pointer moves ok. [There are other strange things about this webpage and Mozilla, but not connected with this bug]
That's not likely to be related to this bug, since the page in question has no BIDI content on it. This bug is specific to BIDI pages.
OK, so I opened new bug entry #118167.
This is based on Andreas Otte's work for bug 57724, which seems to be unlikely to land anytime soon. The patch speeds up the http://www.ynet.co.il site by a factor of 5 and a google search result page (Hebrew, 100 results, search for "mozilla") by a factor of 13. It does not seem to affect the time taken to show the source of cnn.com (a non-bidi page) in any sort of measurable way. I also tried timing load of source for http://www.toronto.com (subject of bug 114420). There I just timed to "first visible source" not to "pageload complete". There was a bit of a difference in favor of the code with this change. All the profiles are at http://www.zbarsky.org:8000/~bzbarsky/viewsource/ The filenames are of the form jprof-whenSiteTokens.#.html. For example, jprof-afterynet128.1.html is loading the ynet.co.il site with the patch (hence "after") with NS_VIEWSOURCE_TOKENS_PER_BLOCK set to 128, and that's data point #1 for that configuration. This brings me to the last issue. I tested various values of NS_VIEWSOURCE_TOKENS_PER_BLOCK. This is the constant that determines how often we start new <pre> blocks. I got down to 8 before I stopped testing -- at 8 tokens/block we're putting one or at most two lines of source inside each block. The patch I'm attaching has the constant set to 8, because that value produced the best results on the test pages in question. More testing on a variety of pages and with various values of that constant would be much appreciated. Simon? rbs? Thoughts?
Correction, it's Andreas Schneider's work that the patch is based on. I need to learn to keep two thoughts in my head at once...
Comment on attachment 67620 [details] [diff] [review] patch implementing ideas from comment 12 and comment 17 These two stay next to each other: + result = mSink->OpenBody(bodyNode); + if(NS_SUCCEEDED(result)) mHasOpenBody=PR_TRUE; + } + IF_FREE(bodyToken,theAllocator); r=rbs, patch looks okay since someone who wants to go back to the old world can pick a big value for NS_VIEWSOURCE_TOKENS_PER_BLOCK. But the default of one block frame per line looks overkill, since this comes at the price of additional memory. If you test something like 15 lines (i.e., the average when keying pageup/pagedown) and see that it is okay, it might be sufficient.
Attachment #67620 - Flags: review+
Attached patch Patch v 1.1Splinter Review
Move the mHasOpenBody line back as rbs suggests, make it easy to disable the whole setup (by setting NS_VIEWSOURCE_TOKENS_PER_BLOCK to 0), only set NS_VIEWSOURCE_TOKENS_PER_BLOCK nonzero when IBMBIDI is defined, make the token count increment only for newline/text/whitespace tokens, raise the threshold which triggers a new block. Now each block has 2-35 lines on the pages I have tested (since a single token can be many lines, eg a <script> tag's contents). Performance is a bit worse than with my original patch, still 4 times faster on ynet.co.il, 10 times faster on google.
Attachment #67620 - Attachment is obsolete: true
Comment on attachment 71583 [details] [diff] [review] Patch v 1.1 Just remove the numerous #ifdef's and replace tests such as + if (mTokenCount > NS_VIEWSOURCE_TOKENS_PER_BLOCK) with + if (NS_VIEWSOURCE_TOKENS_PER_BLOCK > 0 && + mTokenCount > NS_VIEWSOURCE_TOKENS_PER_BLOCK) (since the partitionning is good, let everybody benefit from it by default, not just when bidi is on) r=rbs applies from now on.
Attachment #71583 - Flags: review+
Attached patch Patch v1.2Splinter Review
Comment on attachment 71612 [details] [diff] [review] Patch v1.2 transferring review
Attachment #71612 - Flags: review+
Taking this, since I'm doing the fix anyway.
Assignee: mkaply → bzbarsky
OS: Windows 2000 → All
Priority: -- → P2
Hardware: PC → All
Summary: Mozilla hangs (100% cpu) when doing view source (bidi page) → [FIX]Mozilla hangs (100% cpu) when doing view source (bidi page)
Target Milestone: --- → mozilla1.0
Comment on attachment 71612 [details] [diff] [review] Patch v1.2 sr=jst
Attachment #71612 - Flags: superreview+
Comment on attachment 71612 [details] [diff] [review] Patch v1.2 a=asa (on behalf of drivers) for checkin to 0.9.9. This was approved in email, I'm just flagging the bug.
Attachment #71612 - Flags: approval+
Target Milestone: mozilla1.0 → mozilla0.9.9
Checked in. Page is now most affected by bug 98118. Marking this one fixed.
Status: NEW → RESOLVED
Closed: 24 years ago23 years ago
Resolution: --- → FIXED
Component: Layout: BiDi Hebrew & Arabic → Layout: Text
QA Contact: zach → layout.fonts-and-text
(In reply to comment #21) > This brings me to the last issue. I tested various values of > NS_VIEWSOURCE_TOKENS_PER_BLOCK. This is the constant that determines how often > we start new <pre> blocks. I got down to 8 before I stopped testing -- at 8 > tokens/block we're putting one or at most two lines of source inside each > block. Was there a reason to make the breaking work by counting tokens instead of putting each line in a <pre> without counting tokens?
Yes. The more <pre> the more frames and DOM nodes, the more memory usage and CPU time needed to show the page. Since we only need the multiple <pre> to work around bidi being dumb, we end up with needing a tradeoff between bidi taking too much time and normal layout taking too much time/memory.
Depends on: 649613
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: