Bug 154420 - Website causes massive xorg/konqueror cpu usage (regression)
Summary: Website causes massive xorg/konqueror cpu usage (regression)
Status: RESOLVED FIXED
Alias: None
Product: konqueror
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: unspecified Linux
: NOR normal
Target Milestone: ---
Assignee: Konqueror Developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-12-21 09:17 UTC by Richard Edmands
Modified: 2008-05-26 11:12 UTC (History)
3 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
attempt to workaround -- partly (7.30 KB, patch)
2007-12-21 19:06 UTC, Maksim Orlovich
Details
patch for test/review. (12.05 KB, patch)
2008-01-01 16:29 UTC, Germain Garand
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Edmands 2007-12-21 09:17:16 UTC
Version:            (using KDE KDE 3.97.0)
Installed from:    Ubuntu Packages
OS:                Linux

(regression vs konqueror 3.5.8)
*buntu 8.04
amd athlon 2100+
768mb ddr1 2700
ati 9600se 128mb (xorg ati driver)

hi. in kde 3.5.8, konqueror was able to browse & scroll around textra.podshow.com without noticeable problems.
in kde 4.0rc2... it causes xorg to max out and konqueror only manages to refresh every 5 seconds or so.

appears to be a massive performance regression.

(default settings on both browsers & kde environments)
Comment 1 FiNeX 2007-12-21 09:41:10 UTC
Confirmed. Both konqueror and Xorg process reach about 30% of CPU use (top).
Comment 2 Germain Garand 2007-12-21 15:53:12 UTC
this is caused by prodigal use of CSS opacity feature which is expensive (and wasn't implemented in 3.5).

AFAIKS all browsers supporting opacity have the same problem with this site.
It's every bit as sluggish in Mozilla's and Opera's recent browsers here.

For a very limited gain, I can make the renderer avoid to bother draw anything that has 'opacity: 0' (complete transparency) as I see this site is using that wording in a few places. But that is not going to make a practical difference I'm afraid.

Now there might be room for deeper optimizations as the site does not *visibly* use opacity so much. It could be that some transparent elements are entirely covered by opaque ones.

At this level of expense, it would be quite worth calculating all visible layers rects as we do to have proper z-order on flash widgets, and prune every layer with opacity that is entirely covered.

An interesting chalenge.
Comment 3 Maksim Orlovich 2007-12-21 16:54:57 UTC
I can confirm this being due to opacity, but it's also due to Qt being spectacularily stupid about how it implements most operations with opacity. FiNeX, are you building from source? I have some patches that might help, but it's not bad enough on my machine for me to be sure if they do help.

P.S. We seem to be missing an image here --- or did I mess it up when trying to optimize things?

----------------------------
#0  0xb7f37410 in __kernel_vsyscall ()
#1  0xb62d84c7 in poll () from /lib/i686/libc.so.6
#2  0xb73f9990 in ?? () from /usr/lib/libX11.so.6
#3  0xb73f9d81 in _XRead () from /usr/lib/libX11.so.6
#4  0xb73fa711 in _XReply () from /usr/lib/libX11.so.6
#5  0xb73dd483 in XGetImage () from /usr/lib/libX11.so.6
#6  0xb6839c69 in QPixmap::toImage (this=0x89bc3d8) at image/qpixmap_x11.cpp:756
#7  0xb685b642 in QTexturedBrushData::image (this=0x896fc20) at painting/qbrush.cpp:156
#8  0xb685849e in QBrush::textureImage (this=0x8c621d0) at painting/qbrush.cpp:738
#9  0xb68c82f1 in QSpanData::setup (this=0x8c62318, brush=@0x8c621d0, alpha=230) at painting/qpaintengine_raster.cpp:4841
#10 0xb68d07f8 in QRasterPaintEngine::updateState (this=0x898fcd0, state=@0x9032418) at painting/qpaintengine_raster.cpp:1285
#11 0xb686def9 in QPainterPrivate::updateState (this=0x901cbc8, newState=0x9032418) at painting/qpainter.cpp:600
#12 0xb6877247 in QPainter::drawPath (this=0xbff8ac48, path=@0xbff8ae18) at painting/qpainter.cpp:2486
#13 0xb687365b in QPainterPrivate::draw_helper (this=0x8c74720, originalPath=@0xbff8ae18, op=QPainterPrivate::StrokeAndFillDraw)
    at painting/qpainter.cpp:235
#14 0xb687599b in QPainter::drawRects (this=0xbff8bbac, rects=0xbff8af10, rectCount=1) at painting/qpainter.cpp:2629
#15 0xb77ac6dc in QPainter::drawRect (this=0xbff8bbac, rect=@0xbff8af10)
    at /home/maksim/kde4/src/qt-copy/include/QtGui/../../src/gui/painting/qpainter.h:559
#16 0xb6876e57 in QPainter::drawPixmap (this=0xbff8bbac, r=@0xbff8b020, pm=@0x918e458, sr=@0xbff8b000) at painting/qpainter.cpp:4258
#17 0xb6838710 in QPainter::drawPixmap (this=0xbff8bbac, x=158, y=1507, pm=@0x918e458, sx=0, sy=3, sw=64, sh=61)
    at ../../include/QtGui/../../src/gui/painting/qpainter.h:733
#18 0xb26c4bb0 in khtmlImLoad::PixmapPlane::paint (this=0x9612b90, dx=158, dy=1507, p=0xbff8bbac, sx=0, sy=3, sWidth=75, sHeight=65)
    at /home/maksim/kde4/src/kdelibs/khtml/imload/pixmapplane.cpp:115
#19 0xb26c511c in khtmlImLoad::ImagePainter::paint (this=0x857f228, dx=158, dy=1507, p=0xbff8bbac, sx=0, sy=3, width=75, height=65)
    at /home/maksim/kde4/src/kdelibs/khtml/imload/imagepainter.cpp:126
#20 0xb257d667 in khtml::RenderImage::paint (this=0x94ee084, paintInfo=@0xbff8b390, _tx=158, _ty=1504)
    at /home/maksim/kde4/src/kdelibs/khtml/rendering/render_image.cpp:310

----------------------------

#0  0xb7f07410 in __kernel_vsyscall ()
#1  0xb62a84c7 in poll () from /lib/i686/libc.so.6
#2  0xb73ca08f in ?? () from /usr/lib/libX11.so.6
#3  0xb73ca4ce in _XSend () from /usr/lib/libX11.so.6
#4  0xb73bce79 in ?? () from /usr/lib/libX11.so.6
#5  0xb73bbe6b in ?? () from /usr/lib/libX11.so.6
#6  0xb73bd0e6 in XPutImage () from /usr/lib/libX11.so.6
#7  0xb680ce31 in QPixmap::fromImage (img=@0xbfe141f4, flags=@0xbfe1421c) at image/qpixmap_x11.cpp:1210
#8  0xb683800a in QPaintEngine::drawImage (this=0x8174fd0, r=@0xbfe14510, image=@0xbfe1444c, sr=@0xbfe144f0, flags=@0xbfe14300)
    at painting/qpaintengine.cpp:529
#9  0xb68cad1e in QX11PaintEngine::drawImage (this=0x8174fd0, r=@0xbfe14510, image=@0xbfe1444c, sr=@0xbfe144f0, flags=@0xbfe144ec)
    at painting/qpaintengine_x11.cpp:1588
#10 0xb6843761 in QPainterPrivate::draw_helper (this=0x8b76f18, originalPath=@0xbfe14618, op=QPainterPrivate::StrokeAndFillDraw)
    at painting/qpainter.cpp:245
#11 0xb684547b in QPainter::drawRects (this=0xbfe1523c, rects=0xbfe14710, rectCount=1) at painting/qpainter.cpp:2680
#12 0xb76a86ec in QPainter::drawRect (this=0xbfe1523c, r=@0xbfe14710) at /home/maksim/kde4/src/qt-copy/include/QtGui/../../src/gui/painting/qpainter.h:570
#13 0xb68456b6 in QPainter::fillRect (this=0xbfe1523c, r=@0xbfe14710, brush=@0xbfe14888) at painting/qpainter.cpp:5345
#14 0xb7ea3ab4 in QPainter::fillRect (this=0xbfe1523c, x=356, y=3189, w=402, h=189, b=@0xbfe14888) at /home/maksim/kde4/src/qt-copy/include/QtGui/../../src/gui/painting/qpainter.h:671
#15 0xb24347f1 in khtml::RenderBox::paintBackgroundExtended (this=0x91fa094, p=0xbfe1523c, c=@0xbfe149ec, bgLayer=0x91fd8ac, clipr=
      {x1 = 356, y1 = 3189, x2 = 757, y2 = 3377}, _tx=356, _ty=3189, w=402, h=363, bleft=0, bright=0, pleft=1, pright=1, btop=0, bbottom=0,
    ptop=1, pbottom=1) at /home/maksim/kde4/src/kdelibs/khtml/rendering/render_box.cpp:534
#16 0xb242e685 in khtml::RenderBox::paintBackground (this=0x91fa094, p=0xbfe1523c, c=@0xbfe149ec, bgLayer=0x91fd8ac, clipr=
      {x1 = 356, y1 = 3189, x2 = 757, y2 = 3377}, _tx=356, _ty=3189, w=402, height=363)
    at /home/maksim/kde4/src/kdelibs/khtml/rendering/render_box.cpp:461

Comment 4 Fredrik Höglund 2007-12-21 17:17:34 UTC
If a non-opaque layer is rendered on a pixmap with full opacity,
a possible workaround is to reduce the opacity of the pixmap using
DestinationIn before the pixmap is rendered, like this:

QPainter p(&pixmap);
p.setCompositionMode(QPainter::DestinationIn);
p.fillRect(pixmap.rect(), QColor(0, 0, 0, opacity));

Care must be taken to ensure that the pixmap has an alpha channel, by
calling pixmap.fill(Qt::transparent) when it's created for this to work.

This opacity reduction can be accelerated by the open source Intel driver,
and the ATI driver on R100 and R200 based cards, when in EXA mode.
I expect the proprietary NVidia driver to be able to accelerate it as well.
Comment 5 FiNeX 2007-12-21 18:35:38 UTC
Yes Maksim, send me your patches. I'll test with pleasure :)
Comment 6 Maksim Orlovich 2007-12-21 19:06:11 UTC
Created attachment 22645 [details]
attempt to workaround -- partly

Here it is. Still quite slow, but may be a bit better?

Thanks for testing
Comment 7 Germain Garand 2007-12-21 21:44:02 UTC
this is a good playground too (lot of transforming images with opacity):

http://www.dhteumeuleu.com/runscript.php?scr=photo3D.html

it used to be fast in 3.5 ;/

Comment 8 Germain Garand 2007-12-22 15:17:55 UTC
I can't say I see a significant amelioration with the patch.
Timing scrolling on the site, I get identical figures.
(using Qt 4.3.2...)
Comment 9 Germain Garand 2007-12-24 09:36:38 UTC
SVN commit 752353 by ggarand:

optimize instances of opacity: 0;

CCBUG: 154420


 M  +3 -0      render_layer.cpp  


WebSVN link: http://websvn.kde.org/?view=rev&revision=752353
Comment 10 FiNeX 2007-12-24 11:29:30 UTC
I've just tried the patches but without improvement :-(
Comment 11 Maksim Orlovich 2007-12-24 18:25:43 UTC
Thanks FiNeX. It's good to know, at least.

Germain: it seems that RenderLayer::paintLayer can recurse, and if there are separate opacities set, they don't multiply, right? I guess then to implement Fredrik's suggestion we would have to push the parent alpha down and divide out..

Comment 12 Germain Garand 2007-12-28 14:49:46 UTC
Maks: it should in fact multiply. But looking back at the CSS3 spec, I see opacity is supposed to be a post-rendering, atomic operation anyway. I'll have a shot at rendering the layer off-screen and blend it in one go, if I can stole enough time to my family.
Comment 13 Germain Garand 2008-01-01 16:29:44 UTC
Created attachment 22790 [details]
patch for test/review.

OK, there were several things seriously wrong with our opacity
implementation which this patch addresses (most notably, transparent
objects must establish a stacking context to have proper 
transparency stacking).
Also, opacity is now applied atomically, as the CSS3 spec
draft wants.
Additionnaly, patch provides an extension to the paint buffer to
try to speed things even more.
I'm not completely sure it's worth the trouble though, as it would
need benchmarking on release mode binaries, which I have no time
to compile at the moment.
If anyone has a fully optimized build, please try 
enabling/removing #define USE_PIXMAP_CACHE and do some timings
on e.g scrolling the http://textra.podshow.com site.

All in all, observe a doubling of opacity rendering speed with this patch
applied.
Comment 14 Germain Garand 2008-01-03 18:24:25 UTC
SVN commit 756740 by ggarand:

rework CSS3 opacity, for correctness and workable speed.

.Try hard to minimize the painting region.
.Blend layers atomically after off-screen rendering.
.Rework the PaintBuffer so that it can provide multiple buffers.
.Each transparent object must define a new stacking context so that their
 rendering sub-tree appears as atomic to ancestors, as wanted by CSS3.

CCBUG: 154420


 M  +163 -20   misc/paintbuffer.cpp  
 M  +83 -3     misc/paintbuffer.h  
 M  +22 -9     rendering/render_layer.cpp  
 M  +5 -4      rendering/render_object.cpp  
 M  +3 -2      rendering/render_replaced.cpp  
 M  +6 -6      rendering/render_style.h  


WebSVN link: http://websvn.kde.org/?view=rev&revision=756740
Comment 15 Germain Garand 2008-01-05 21:02:58 UTC
(by the way Maksim, OT but if I go to the reported site with debugger enabled, I get a crash - dereference of a null Document pointer in DebugWindow::enterContext)
Comment 16 Maksim Orlovich 2008-01-09 21:47:33 UTC
SVN commit 759026 by orlovich:

Fix the debugger crash spart noticed on 154420. We were killing source
code information on eval fragments which had functions which escaped..

Inellegant, but effective
CCBUG:154420

 M  +11 -0     debugdocument.cpp  
 M  +7 -0      debugdocument.h  
 M  +8 -3      debugwindow.cpp  


WebSVN link: http://websvn.kde.org/?view=rev&revision=759026
Comment 17 Fredrik Höglund 2008-05-18 23:49:21 UTC
SVN commit 809426 by fredrik:

Improve performance when rendering CSS opacity layers, by using
CompositionMode_DestinationIn to reduce the alpha of the layers
before rendering them, instead of using QPainter::setOpacity().

With this change we no longer end up in
QPainterPrivate::draw_helper(), and the rendering is fully
accelerated in hardware with drivers that accelerate Xrender.

BUG: 154420


 M  +4 -1      paintbuffer.h  


WebSVN link: http://websvn.kde.org/?view=rev&revision=809426
Comment 18 FiNeX 2008-05-26 11:12:56 UTC
http://www.dhteumeuleu.com/runscript.php?scr=photo3D.html 
is still CPU consuming (about 30-40% of a P4@2600Mhz), moreover there is a lot of flickering.

Instead http://textra.podshow.com is better, the CPU use is quite regular.