First off, apologies for a bug report with precious few details. I am hoping this rings a bell for some cairo developer. The Gnumeric team has received a few reports of severe cpu usage when we do our "walking ants" animation that marks a copied selection. I do not see this on my Linux machine; I might see it with our win32 binary under wine, but that's a whole lot of extra variables. To see the walking ants animation in action, start Gnumeric, select a large area, and press ctrl-c. Alternatively, watch http://jeff.ecchi.ca/public/gnumeric-381011.webm Here's what the animation code does: 1. We set a two-item dashed line style using cairo_set_dash. 2. We set a line width using cairo_set_line_width 3. We set one of the two ant colours. 4. We set a rectangle path using cairo_rectangle 5. We draw a line along that path using cairo_stroke_preserve. [That draws half the ant pattern, say the black bits.] 6. We set the other ant colour. 7. We set the stipple with an offset of one "ant" length 8. We draw a line along that path using cairo_stroke. [That draws half the ant pattern, say the wite bits.] Repeat that every 150ms with the two colours swapped. The actual code is at https://git.gnome.org/browse/gnumeric/tree/src/item-cursor.c near line 450. Is there any reason why this should bring a modern machine to its knees? Further random info: Both my Linux and win32 cairo are 1.12.16. One original bug report for this: https://bugzilla.gnome.org/show_bug.cgi?id=381011 starting at comment 12.
I don't really understand the code, but here is what I think I found. The 150ms timeout is implemented in item_cursor_realize() in item-cursor.c. For items with ->style == GNM_ITEM_CURSOR_ANTED it does this: ic->animation_timer = g_timeout_add (150, (GSourceFunc) cb_item_cursor_animation, ic); Looking at the callback function, we see that it just toggles ic->state and calls goc_item_invalidate() on the item. I haven't actually found that function's implementation, but debian code search gave me the following (goc_item_invalidate(item) just calls goc_item_maybe_invalidate(item, FALSE);): http://sources.debian.net/src/goffice/0.10.9-1/goffice/canvas/goc-item.c?hl=473#L451 This calculates the bounds of the items and invalidates that rectangle on the canvas. TL;DR: gnumeric redraws "basically all of its content" about 7 times per second and then wonders that this is slow. (Or did I miss something?) Re "this used to work fine for over a decade": The implementation a decade ago was more intelligent (I guess instead of redrawing things, it just drew the ant line ones and then used an XOR operator to "toggle the dashes/ants").
And valgrind --tool=callgrind says that 65% of CPU time is spent inside gnm_style_borders_row_draw() (unrelated code?) which itself spends most of its cpu time in cairo_stroke(). So the high cpu usage seems to come from some unrelated code which just happens to be executed more often due to the "ant lines". I don't see why this would be a cairo problem. Could you provide more information, perhaps some self-contained C code that shows cairo being slow?
Thanks for the analysis and the effort. I am now able to reproduce the problem myself and work on it. Apologies for having suspected cairo: this was hitting a random set of machines suggesting something below gtk+. In fact, I now believe this is something as simple as different screen resolution. More pixels, more work. And pixels go up with resolution squared.
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.