Bug 20831

Summary: Very slow <input type="search">. 100% CPU usage for each key press.
Product: WebKit Reporter: John Engelhart <john.engelhart>
Component: TextAssignee: Nobody <webkit-unassigned>
Status: RESOLVED WORKSFORME    
Severity: Normal CC: simon.fraser
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Mac   
OS: OS X 10.5   

John Engelhart
Reported 2008-09-13 12:52:32 PDT
Very, very slow interactive response for a <input type="search"> field. CPU jumps to 100% for each key press, and can take a few seconds for just a dozen keystrokes. I've condensed down the HTML that reproduces the bug. Tried with nightly r35942 and Mac OS X Safari 4.0 (5528.1, I think the latest developer preview available). I also grabbed a stack sample and included the heavy hitting part in the html comments. I have no idea which of the bits and pieces cause the problem, so the HTML code that I'm including is the result of distilling the problem down in to something minimal that definitely reproduces the issue. The nightly build is noticeably more sluggish than the Safari 4 developer preview, but not by much. --- begin HTML code to reproduce problem --- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <style type="text/css"> .alphaTopAndBottomFade { border-bottom: 1px solid rgba(0,0,0,0.075); border-top: 1px solid rgba(0,0,0,0.2); border-left: 1px solid rgba(0,0,0,0.05); border-right: 1px solid rgba(0,0,0,0.05); -webkit-box-shadow: 0px 0px 1px rgba(0,0,0,0.2); padding-bottom: 0.5em; margin-bottom: 0.5em; background: -webkit-gradient(linear, left top, left bottom, from(rgb(213,221,231)), color-stop(0.33, rgb(255,255,255)), color-stop(0.66, rgb(255,255,255)), to(rgb(240,240,240))); -webkit-border-radius: 5px; -moz-border-radius: 5px; } .table { display: table; } .table > .row { display: table-row; } .table > .row > .cell { display: table-cell; } </style> </head> <body> <div class="content" style=""> <div class="alphaTopAndBottomFade" style="position: relative;"> <div class="table" style="width: 100%; height: 300px; padding: 0.375em 3ex;"><div class="row"> <div class="cell" style="width: 50%; height: 100%;"> <div style="width: 100%; height: 100%; position: relative;"> <div style="margin: 0em 3ex; color: #333; font-family: 'Lucida Grande'; font-weight: normal;"> <div style="font-size: 18px; font-weight: normal;">Title</div> <div style="color: #666; margin-left: 1ex; margin-top: 0.25em;">Subtitle!</div> </div> <div style="font: 11px normal 'Lucida Grande'; color: #555"> <p>Yay for us.. and stuff</p> <p>And some more bits and pieces.</p> <!-- This input search box is very, very slugish to respond to key presses, and chews up 100% CPU on a G4 PPC PowerBook --> <!-- I don't know which of the above pieces contribute to the problem, but I sliced it down to just these bits that reproduce the problem. Note: When I was trimming things down to a useable example, there's definitely some point where the problem 'mostly' goes away. Also, I don't know if this is a WebKit bug or a Mac OS X compositor performance issue. --> <input type="search" name="req" value="" results="5" placeholder="Search This" autosave=""> <!-- Stack sample during bad behavior (clipped for brevity, heaviest call stack only): Analysis of sampling Safari (pid 37724) every 10 milliseconds Call graph: 1254 Thread_2503 1254 0xbffff050 1254 0xb65a0 1254 NSApplicationMain 1254 -[NSApplication run] 1200 0x7dac 1200 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] 1200 _DPSNextEvent 966 BlockUntilNextEventMatchingListInMode 966 ReceiveNextEventCommon 965 RunCurrentEventLoopInMode 962 CFRunLoopRunSpecific 843 __CFRunLoopDoObservers 834 _handleWindowNeedsDisplay 831 0x1ff80 831 -[NSWindow displayIfNeeded] 826 -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] 807 -[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 807 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 806 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 803 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 798 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 782 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 774 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 773 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 772 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 771 -[WebHTMLView(WebPrivate) _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 771 -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] 771 -[NSView _drawRect:clip:] 771 -[WebHTMLView drawRect:] 771 -[WebHTMLView drawSingleRect:] 771 -[WebFrame(WebInternal) _drawRect:] 771 WebCore::Frame::paint(WebCore::GraphicsContext*, WebCore::IntRect const&) 771 WebCore::RenderLayer::paintLayer(WebCore::RenderLayer*, WebCore::GraphicsContext*, WebCore::IntRect const&, bool, WebCore::PaintRestriction, WebCore::RenderObject*, bool) 770 WebCore::RenderLayer::paintLayer(WebCore::RenderLayer*, WebCore::GraphicsContext*, WebCore::IntRect const&, bool, WebCore::PaintRestriction, WebCore::RenderObject*, bool) 765 WebCore::RenderLayer::paintLayer(WebCore::RenderLayer*, WebCore::GraphicsContext*, WebCore::IntRect const&, bool, WebCore::PaintRestriction, WebCore::RenderObject*, bool) 758 WebCore::RenderBlock::paint(WebCore::RenderObject::PaintInfo&, int, int) 757 WebCore::RenderBlock::paintObject(WebCore::RenderObject::PaintInfo&, int, int) 750 WebCore::RenderBox::paintBoxDecorations(WebCore::RenderObject::PaintInfo&, int, int) 744 WebCore::RenderBox::paintFillLayer(WebCore::RenderObject::PaintInfo const&, WebCore::Color const&, WebCore::FillLayer const*, int, int, int, int, int, int, WebCore::CompositeOperator) 744 WebCore::RenderBox::paintFillLayerExtended(WebCore::RenderObject::PaintInfo const&, WebCore::Color const&, WebCore::FillLayer const*, int, int, int, int, int, int, WebCore::InlineFlowBox*, WebCore::CompositeOperator) 744 WebCore::GraphicsContext::drawTiledImage(WebCore::Image*, WebCore::IntRect const&, WebCore::IntPoint const&, WebCore::IntSize const&, WebCore::CompositeOperator) 744 WebCore::Image::drawTiled(WebCore::GraphicsContext*, WebCore::FloatRect const&, WebCore::FloatPoint const&, WebCore::FloatSize const&, WebCore::CompositeOperator) 744 WebCore::GeneratedImage::drawPattern(WebCore::GraphicsContext*, WebCore::FloatRect const&, WebCore::AffineTransform const&, WebCore::FloatPoint const&, WebCore::CompositeOperator, WebCore::FloatRect const&) 635 WebCore::Image::drawPattern(WebCore::GraphicsContext*, WebCore::FloatRect const&, WebCore::AffineTransform const&, WebCore::FloatPoint const&, WebCore::CompositeOperator, WebCore::FloatRect const&) 635 CGContextDrawTiledImage 635 CGContextFillRect 635 CGContextFillRects 635 ripc_DrawRects 635 ripc_Render 628 ripc_GetColor 624 ripc_TilePattern 624 ripc_DrawImages 623 ripc_RenderImage 623 ripl_BltImage 623 ripl_Mark 623 ARGB32_image 623 vecCGSBlendXXXX8888Permute 623 vecCGSBlendXXXX8888Permute 1 ripc_AcquireImage 1 CGSImageDataLock 1 img_reference 1 img_reference 4 ripl_Create 4 mem_allocate 3 mmap 3 mmap 1 mem_allocate 6 ripl_release 6 mem_deallocate 6 munmap$UNIX2003 6 munmap$UNIX2003 1 ripl_BltShape 1 dyld_stub_CGSBoundsIntersection 1 dyld_stub_CGSBoundsIntersection 38 WebCore::ImageBuffer::create(WebCore::IntSize const&, bool) 34 WTF::tryFastCalloc(unsigned long, unsigned long) 34 __bzero 34 __bzero 4 CGBitmapContextCreate --> </div> </div> </div> </div> </div> </div> </div> </body> </html>
Attachments
John Engelhart
Comment 1 2008-09-15 16:13:17 PDT
While doing more web page hacking, it's become pretty clear that the following combination causes a huge CPU spike (on a 1.5 GHz g4 powerbook): Some kind of container (div). A webkit transition, preferably one that infinitely loops. And the one that really breaks the bank: Some element in the render hiearchy that is a parent for the animating webkit element must have a background: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.25)), to(rgba(0,0,0,1.0))); (or equiv). The use of rgba / alpha in the gradient doesn't seem to matter, all that's needed is the gradient. Hopefully this helps narrow things down.
John Engelhart
Comment 2 2008-09-15 16:14:29 PDT
Crap. Strike my last (comment #1). Pasted to the wrong bug. :(.
John Engelhart
Comment 3 2008-09-19 01:07:28 PDT
I now strongly suspect that this bug is related to a different bug I've just recently filed: bug # 20929. I tested this bugs included snippet and removed the border attributes for .alphaTopAndBottomFade and the problem went away.
Simon Fraser (smfr)
Comment 4 2009-01-03 17:06:57 PST
Bad search field redrawing in the testcase filed as bug 23093. John: if I extract the HTML you posted (with the garbage in the middle removed), typing in the search field seems fine. Please attach an HTML file that shows the problem using the Create New Attachment link above.
John Engelhart
Comment 5 2009-01-03 20:59:53 PST
(In reply to comment #4) > Bad search field redrawing in the testcase filed as bug 23093. > > John: if I extract the HTML you posted (with the garbage in the middle > removed), typing in the search field seems fine. Please attach an HTML file > that shows the problem using the Create New Attachment link above. > I just retested this as requested. I tested it on a late 2008 unibody MacBook (2.0GHz) and a 1.5GHz PPC PowerMac. The problem doesn't really manifest itself in any noticeable fashion on the faster machine. Only on the slower powerbook is it noticeable. Just tried forcing Safari.app to execute under Rosetta and it's slightly noticeable, but still not to the degree that it is on the powerbook. I'm afraid to really see this in action, you'll need to find yourself an old PPC machine. For grins, I tried it on an iPod touch, but it handles the text input in a completely different way, so can't really test it that way unfortunately. IMHO, the machines are fast enough now that you can't really perceive a problem any more. However (and this is just a guy feeling) I think it still points to an underlying performance problem, possibly in the rendering code. Thinking back, I remember digging a little bit more in to this, and I seem to remember coming to the conclusion that it seemed like a case of 'over redrawing', that each keystroke triggered a storm of unnecessary redraws. My initial comment says that getting rid of the -webkit-gradient background causes the problem to go away... does that ring any bells? Something about having a -webkit-gradient in the 'NSView' (sorry, I don't know webkit all that well, but whatever is analogous to the cocoa NSView paradigm) hierarchy that might be causing some over-zealous redraw/refresh? So, just to be clear: The problem still exists on my 1.5GHz PPC PowerBook, but isn't noticeable on a 2.0GHz x86 late 2008 unibody MacBook. Hmm, for grins, I just tried the example HTML unmodified in one table, and commenting out the .alpha... CSS part in another tab on my MacBook, and then typing in both search boxes. Watching MenuMeter's CPU usage, the unmodified version does use a noticeable (but small) amount of CPU, and the commented out version uses an undetectable amount of CPU. I suspect that a Shark.app session between the two versions (unmodified, and .alpha... CSS commented out) would be revealing to someone who knows the code base.
Simon Fraser (smfr)
Comment 6 2009-01-04 10:46:54 PST
If there really is a perf issue, it should be possible to cook up a testcase that shows it even on faster machines. Maybe try lots of gradient divs layered under the search field, or something? However, without a testcase showing the problem in an obvious way, it's not going to get attention.
Note You need to log in before you can comment on or make changes to this bug.