Bug 20831 - Very slow <input type="search">. 100% CPU usage for each key press.
Summary: Very slow <input type="search">. 100% CPU usage for each key press.
Status: RESOLVED WORKSFORME
Alias: None
Product: WebKit
Classification: Unclassified
Component: Text (show other bugs)
Version: 528+ (Nightly build)
Hardware: Mac OS X 10.5
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-09-13 12:52 PDT by John Engelhart
Modified: 2009-01-04 10:46 PST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description John Engelhart 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>
Comment 1 John Engelhart 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.
Comment 2 John Engelhart 2008-09-15 16:14:29 PDT
Crap.  Strike my last (comment #1).  Pasted to the wrong bug.  :(.
Comment 3 John Engelhart 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.
Comment 4 Simon Fraser (smfr) 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.
Comment 5 John Engelhart 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.
Comment 6 Simon Fraser (smfr) 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.