Bug 32014

Summary: GTK programs in cairo 1.10 are sluggish over NX
Product: cairo Reporter: Ryan Prichard <ryan.prichard>
Component: xlib backendAssignee: Carl Worth <cworth>
Status: RESOLVED MOVED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: medium CC: eric.sirianni, eugenesan, freedesktop, jens.hoelldampf, lpurvis, pavel.sidlo, stephen, steven
Version: 1.10.0   
Hardware: x86 (IA32)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:

Description Ryan Prichard 2010-12-01 04:12:12 UTC
I use NX to connect to a work computer from home, over the Internet.  I recently upgraded to Ubuntu 10.10, and I noticed that GTK programs became very sluggish.

I currently have 1.10.0-1ubuntu3 of libcairo2 installed. If I override this with the Ubuntu 10.04 version of libcairo2, 1.8.10-2ubuntu1, performance is restored. I used LD_LIBRARY_PATH to run GTK programs with the old libcairo2 package.

I first reported this issue against Ubuntu 10.10, but since the problem is in Cairo (or NX), an Ubuntu maintainer suggested I report it here.  The Ubuntu bug report is at https://bugs.launchpad.net/ubuntu/+source/cairo/+bug/682338.  It has a video attached demonstrating how much faster gedit is using the old libcairo2 package.

Both the home and work computer run Ubuntu 10.10.

In addition to the performance drop, I see JPEG artifacts on rendered text and metacity window decorations.  I'm used to seeing some artifacts because NX compresses things like icons with JPEG.  NX doesn't normally compress text, window decorations, etc.  The slow performance and artifacts suggests that NX is transmitting bitmap data when it should be transmitting drawing commands.

The work computer has these NX packages installed:
nxclient-3.4.0-7
nxnode-3.4.0-14
nxserver-3.4.0-14

The home computer only has the nxclient-3.4.0-7 package installed.

The ping times from my home computer to work computer are about 35ms.

I made a Cairo Git checkout and verified that when I built 1.8.10, gedit was fast, but when I built the newest version, gedit was slow.  git bisect identified a single commit where the performance problem began:

commit 33be73dfb76c26e3bb0ab59b2f570d00d9c7be62
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Sep 11 14:59:58 2009 +0100

    [xlib] Fix big-line.
    
    Project lines that exceed the 16.16 limits onto the XFixedLine, as we know
    that top/bottom must fit within the confines of the surface and so will be
    less than 16 bits.
    
    Sadly this is a run-on patch that also does:
    1. Make FillTiled the default for new GCs.
    2. Stores extend mode as opposed to repeat, and thereby cleaning up some
    inconsistent code.
    3. Remove the special casing for unbounded trapezoids, as it is redundant
    with the polygon clipping.
    4. Tidy the logic for deciding when to use the core protocol
    (_categorize_composite_operation)

When I searched the Internet for "Ubuntu 10.10 slow NX", I noticed a similar-looking problem reported on a forum.
 - http://ubuntuforums.org/showthread.php?t=1625513
Comment 1 Levi Purvis 2011-05-08 20:07:04 UTC
I can confirm this bug.  I have the same problem and it is resolved by downgrading cairo to 1.8.10.
Comment 2 Pavel Sidlo 2011-05-09 06:02:47 UTC
I have the same problem. Downgraded Cairo to 1.8.10 too.
Comment 3 Steven Robertson 2011-06-18 12:39:42 UTC
This appears to be due to having 'display->buggy_repeat' set in _cario_xlib_device_create(). NX (3.5, at least) presents itself as an X.Org server with version 60900000, which trips the 'buggy_repeat' flag. 

'buggy_repeat' is set on X.Org 6.9 to avoid a bug which will crash the X server. On NX 3.5, running the 'extend-reflect' test case after forcing the buggy_repeat flag to FALSE on git rev ced061124d0b402c did not crash the X server, so it is possible this bug does not need to be worked around on NX servers. (The test application crashes on svg11 and svg12 test modes, and fails on others, but it doesn't crash the X server itself. Plus, NX fails many other tests, and other tests *will* crash the server; not exactly a bastion of correctness.)

Cairo will use software compositing for some operations, preventing NX from doing its X11 protocol compression magic to send text in an efficient manner. The commit indicated by Ryan Prichard causes more operations than before to use software compositing. I'm not sure if this was intentional or not.

I see three reasonable solutions:

* Get NoMachine to update NX's reported version number. My current employer makes extensive use of NX; I'll try to have someone talk to them about this.

* Detect and whitelist NX for buggy_repeat using an out-of-band mechanism.

* Revert to the (possibly incorrect?) stricter test for falling back to software rendering.

In the mean-time, users can apply this patch to Cairo to work around the workaround. I'm not recommending that this patch be applied to Cairo itself, it's just for NX users who can't stand the slowness. Applies to current git HEAD, but probably works fine with 1.10 too.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index f8caf83..ffaa344 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1994,8 +1994,8 @@ _recategorize_composite_operation (cairo_xlib_surface_t         *dst,
            return DO_XTILE;
     }
 
-    if (dst->buggy_repeat && src_attr->extend == CAIRO_EXTEND_REPEAT)
-       return DO_UNSUPPORTED;
+    //if (dst->buggy_repeat && src_attr->extend == CAIRO_EXTEND_REPEAT)
+       //return DO_UNSUPPORTED;
 
     if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
        return DO_UNSUPPORTED;
Comment 4 Andrea Canciani 2011-06-20 01:42:02 UTC
(In reply to comment #3)
> This appears to be due to having 'display->buggy_repeat' set in
> _cario_xlib_device_create(). NX (3.5, at least) presents itself as an X.Org
> server with version 60900000, which trips the 'buggy_repeat' flag. 
> 
> 'buggy_repeat' is set on X.Org 6.9 to avoid a bug which will crash the X
> server. On NX 3.5, running the 'extend-reflect' test case after forcing the
> buggy_repeat flag to FALSE on git rev ced061124d0b402c did not crash the X
> server, so it is possible this bug does not need to be worked around on NX
> servers. (The test application crashes on svg11 and svg12 test modes, and fails
> on others, but it doesn't crash the X server itself. Plus, NX fails many other
> tests, and other tests *will* crash the server; not exactly a bastion of
> correctness.)
> 
> Cairo will use software compositing for some operations, preventing NX from
> doing its X11 protocol compression magic to send text in an efficient manner.
> The commit indicated by Ryan Prichard causes more operations than before to use
> software compositing. I'm not sure if this was intentional or not.
> 
> I see three reasonable solutions:
> 
> * Get NoMachine to update NX's reported version number. My current employer
> makes extensive use of NX; I'll try to have someone talk to them about this.
> 
> * Detect and whitelist NX for buggy_repeat using an out-of-band mechanism.
> 
> * Revert to the (possibly incorrect?) stricter test for falling back to
> software rendering.

Another (untested) possibility is to use the xlib-xcb functions.
Is NX sluggish on a cairo library compiled with --enable-xlib-xcb ?

> 
> In the mean-time, users can apply this patch to Cairo to work around the
> workaround. I'm not recommending that this patch be applied to Cairo itself,
> it's just for NX users who can't stand the slowness. Applies to current git
> HEAD, but probably works fine with 1.10 too.
> 
> diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
> index f8caf83..ffaa344 100644
> --- a/src/cairo-xlib-surface.c
> +++ b/src/cairo-xlib-surface.c
> @@ -1994,8 +1994,8 @@ _recategorize_composite_operation (cairo_xlib_surface_t  
>       *dst,
>             return DO_XTILE;
>      }
> 
> -    if (dst->buggy_repeat && src_attr->extend == CAIRO_EXTEND_REPEAT)
> -       return DO_UNSUPPORTED;
> +    //if (dst->buggy_repeat && src_attr->extend == CAIRO_EXTEND_REPEAT)
> +       //return DO_UNSUPPORTED;
> 
>      if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
>         return DO_UNSUPPORTED;
Comment 5 Steven Robertson 2011-06-20 22:29:05 UTC
It certainly seems to have an effect - reliable server crash when launching GEdit with git rev ced061124d0b402c is compiled with --enable-xlib-xcb (binary loaded via LD_LIBRARY_PATH, so crash is probably not gedit-specific). I can try to scrounge up additional information if it's needed here, but with NX being quasi-closed-source it may not be easy or helpful to do so.

Although it does end up crashing *very* quickly, so it solves the performance problem in one sense.
Comment 6 Andrea Canciani 2011-06-21 00:00:41 UTC
(In reply to comment #5)
> It certainly seems to have an effect - reliable server crash when launching
> GEdit with git rev ced061124d0b402c is compiled with --enable-xlib-xcb (binary
> loaded via LD_LIBRARY_PATH, so crash is probably not gedit-specific). I can try
> to scrounge up additional information if it's needed here, but with NX being
> quasi-closed-source it may not be easy or helpful to do so.

A server crash should never happen, no matter what the application does.
If it is easy to reproduce, it might be an useful bugreport for NX developers.

> 
> Although it does end up crashing *very* quickly, so it solves the performance
> problem in one sense.
Comment 7 Manuel Siggen 2012-01-03 06:56:22 UTC
NX developers have been informed : 

   http://www.nomachine.com/tr/view.php?id=TR01J02646
Comment 8 Levi Purvis 2012-01-03 20:54:32 UTC
The quick-fix patch suggested in comment #3 resolved the issue for me in Ubuntu 11.10.  I applied the patch against Ubuntu's cairo source package 1.10.2-6ubuntu3 (the offsets had to be adjusted a bit).
Comment 9 Eric 2014-07-25 20:58:52 UTC
I'm having trouble applying this patch to libcairo2 version 1.13.0 from Ubuntu 14.04

Doing some tracing, it looks like display->buggy_repeat is accessed by the function:

cairo_bool_t
_cairo_xlib_display_has_repeat (cairo_device_t *device)
{
    return ! ((cairo_xlib_display_t *) device)->buggy_repeat;
}

However, I don't see that function called anywhere else in the code.

I'm still observing slowness for GTK programs using NX (both nx2go and NoMachine).

Could anyone comment on the proper patch for libcairo2 version 1.13.0?

I'm also having trouble locating the callers of _recategorize_composite_operation.  Perhaps I have an incomplete source tree?
$ find -type f | xargs grep recategorize_composite
./cairo-xlib-render-compositor.c:    operation = _recategorize_composite_operation (dst, op, src, &src_attr,
./cairo-xlib-render-compositor.c:    operation = _recategorize_composite_operation (dst, op, src,
Comment 10 GitLab Migration User 2018-08-25 13:57:47 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/290.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.