[cairo] Very slow performance

TOKUNAGA Hiroyuki tkng at xem.jp
Sun Dec 26 01:36:35 PST 2004


Hi,

On Thu, 23 Dec 2004 15:20:50 -0500
Chris <fltk at functionalfuture.com> wrote:

> Are there possibly some super-fast routines that would work here?
> Filling a rectangle is so common that I would think there are a ton of
> options here.  Possibly using hardware acceleration since just about
> every computer has some sort of blitter available.

I made a faster version of pixman_fill_rect_32bbp by unrolling the inner
loop. But I noticed that real problem is not pixman_fill_rect_32bbp
itself, but too many times calling of pixman_fill_rect_32bbp. It was
called about 3000 times where width = 1688, height = 454.

In most case, pixman_fill_rect_32bbp was called from
cairo_surface_create_similar which called from _svg_cairo_begin_element.
But, created surface doesn't seem used from anywhere. Attached patch
will reduce the calling of cairo_surface_create_similar.

I tested via $ svg2png centi_unfinished.svg centi_unfinished.png

Before applied, it takes about 17.5 seconds on my machine. After
applied, it takes about 3 seconds on my machine. (500% faster than
before!)


libpixman-fill-rect-unrolling.diff: It does only loop unrolling, doesn't
use MMX nor SSE, though obviously we should use them. This patch reduce
test running time from about 17.5 seconds to about 15.5 seconds only,
not so efficient.

livsvg-cairo-not-create-surface.diff: Generated png seems correct, but
I'm not confident in this patch, I want someone's review. This patch
reduce test running time from about 15.5 seconds to about 3 seconds.


Regards,

-- 
TOKUNAGA Hiroyuki
tkng at xem.jp
http://kodou.net/
-------------- next part --------------
Index: svg_cairo_state.c
===================================================================
RCS file: /cvs/cairo/libsvg-cairo/src/svg_cairo_state.c,v
retrieving revision 1.11
diff -u -r1.11 svg_cairo_state.c
--- svg_cairo_state.c	2 Aug 2004 20:16:37 -0000	1.11
+++ svg_cairo_state.c	26 Dec 2004 08:54:36 -0000
@@ -83,12 +83,7 @@
 
     *state = *other;
 
-    if (other->child_surface)
-	state->child_surface = cairo_surface_create_similar (other->child_surface,
-						      CAIRO_FORMAT_ARGB32,
-						      state->viewport_width,
-						      state->viewport_height);
-
+    state->child_surface = NULL;
     if (other->font_family)
 	state->font_family = strdup ((char *) other->font_family);
 
-------------- next part --------------
Index: icrect.c
===================================================================
RCS file: /cvs/cairo/libpixman/src/icrect.c,v
retrieving revision 1.12
diff -u -r1.12 icrect.c
--- icrect.c	23 Dec 2004 19:00:01 -0000	1.12
+++ icrect.c	26 Dec 2004 09:34:49 -0000
@@ -58,21 +58,31 @@
 {
     uint32_t int_pixel;
     char *line;
-    char *data;
-    int w;
+    uint32_t *data;
+    uint32_t w;
+
+    data = (uint32_t *)((char *)dst->pixels->data +
+		      xDst * 4 + yDst * dst->pixels->stride);
 
-    line = (char *)dst->pixels->data +
-	xDst * 4 + yDst * dst->pixels->stride;
-     
     int_pixel = *(uint32_t *)pixel;
-    while (height-- > 0) {
-	data = line;
-	w = width;
-	while (w-- > 0) {
-	    *(uint32_t *)data = int_pixel;
-	    data += 4;
+
+    while (height-- != 0) {
+
+      for(w = width; w > 8; w-= 8) {
+	  data[w] = int_pixel;
+	  data[w - 1] = int_pixel;
+	  data[w - 2] = int_pixel;
+	  data[w - 3] = int_pixel;
+	  data[w - 4] = int_pixel;
+	  data[w - 5] = int_pixel;
+	  data[w - 6] = int_pixel;
+	  data[w - 7] = int_pixel;
 	}
-	line += dst->pixels->stride;
+
+	while(w-- != 0) {
+	  data[w] = int_pixel;
+	}
+	data = (uint32_t *)((char *)data + dst->pixels->stride);
     }
 }
 


More information about the cairo mailing list