> I forgot to ask that you measure CPU consumption on the server: > You could have (manually) enable better compression schemes for the images, which would have reduced the total bytes sent. > That costs CPU, though. I did perform a crude version of that measurement (jiffies for the Xorg process). I didn't include it in the results, as I was trying to keep my message focused (brevity is not a natural strength of mine :-/). The Libre Office case used 1945 jiffies for unmodified Spice; 590 with the deferred_fps patch. The Word 2007 test used 1294 jiffies unmodified, and 932 with the deferred_fps patch. That suggests that my approach certainly does not add to the CPU burden (which is not surprising, if you review the code paths relative to the operation stream). > > BTW, if you could post a (compressed) capture of your traffic, should be fairly easy to evaluate how many images were sent, how many were cached, and how many other commands were sent. May help focus on the important stuff to optimize, from bandwidth point of view. Actually, I spent a fair amount of time instrumenting the stream, so I think I understand the traffic reasonably well. I've attached the latest iteration of one of the patches I used to analyze the traffic. I have another patch which records wire operations in and out of the spice server, and while it has actual traffic data I wanted, it lacks the specificity of uxa operation that I craved. And, again, when I ran that instrumentation for my test cases, I found that the stream was so overwhelmingly dominated by certain operations that all the other information (e.g. images, caching, and so on) seemed irrelevant. I don't have exact numbers in front of me at the moment, but my recollection was that solid() (e.g. region fill) based calls represented over 95% of the traffic in the Libre Office test case. Cheers, Jeremy
diff --git a/src/qxl_surface.c b/src/qxl_surface.c index 113f09b..a6d3c0c 100644 --- a/src/qxl_surface.c +++ b/src/qxl_surface.c @@ -49,6 +49,8 @@ #include "qxl.h" +#include <sys/time.h> + #ifdef DEBUG_SURFACE_LIFECYCLE #include <stdio.h> @@ -128,6 +130,15 @@ struct surface_cache_t qxl_surface_t *cached_surfaces[N_CACHED_SURFACES]; }; +static char * jpw_timestamp(void) +{ + struct timeval t; + static char buf[256]; + gettimeofday(&t, NULL); + sprintf(buf, "%ld.%ld", t.tv_sec, t.tv_usec); + return buf; +} + #ifdef DEBUG_SURFACE_LIFECYCLE static void debug_surface_open(void) { @@ -650,6 +661,8 @@ retry: cmd->u.surface_create.data = physical_address (qxl, surface->address, qxl->vram_mem_slot); + ErrorF("Q%s %s surface_create %d: width %d, height %d\n", + uxa_in_composite() ? "r" : "", jpw_timestamp(), surface->id, width, height); push_surface_cmd (cache, cmd); dev_addr = (uint32_t *)((uint8_t *)surface->address + stride * (height - 1)); @@ -762,6 +775,8 @@ send_destroy (qxl_surface_t *surface) pixman_image_unref (surface->host_image); cmd = make_surface_cmd (surface->cache, surface->id, QXL_SURFACE_CMD_DESTROY); + ErrorF("Q%s %s surface_destroy %d\n", + uxa_in_composite() ? "r" : "", jpw_timestamp(), surface->id); push_surface_cmd (surface->cache, cmd); } @@ -989,6 +1004,8 @@ real_upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2) uint32_t *data; int stride; + ErrorF("Q%s %s upload_box %d: x1 %d, y1 %d, x2 %d, y2 %d\n", + uxa_in_composite() ? "r" : "", jpw_timestamp(), surface->id, x1, y1, x2, y2); rect.left = x1; rect.right = x2; rect.top = y1; @@ -1231,6 +1248,10 @@ qxl_surface_solid (qxl_surface_t *destination, struct QXLRect qrect; uint32_t p; + ErrorF("Q%s %s qxl_surface_solid %d: %d, %d, %d, %d to pixel 0x%lx\n", + uxa_in_composite() ? "r" : "", + jpw_timestamp(), destination->id, x1, y1, x2, y2, destination->u.solid_pixel); + qrect.top = y1; qrect.bottom = y2; qrect.left = x1; @@ -1267,6 +1288,10 @@ qxl_surface_copy (qxl_surface_t *dest, struct QXLDrawable *drawable; struct QXLRect qrect; + ErrorF("Q%s %s qxl_surface_copy %p from %p: src (%d, %d) dest (%d, %d) width %d, height %d\n", + uxa_in_composite() ? "r" : "", + jpw_timestamp(), + dest, dest->u.copy_src, src_x1, src_y1, dest_x1, dest_y1, width, height); #ifdef DEBUG_REGIONS print_region (" copy src", &(dest->u.copy_src->access_region)); print_region (" copy dest", &(dest->access_region)); @@ -1339,6 +1364,11 @@ qxl_surface_put_image (qxl_surface_t *dest, struct QXLRect rect; struct QXLImage *image; + ErrorF("Q%s %s qxl_surface_put_image %d: x %d, y %d, width %d, height %d, src %p, pitch %d\n", + uxa_in_composite() ? "r" : "", + jpw_timestamp(), + dest->id, x, y, width, height, src, src_pitch); + rect.left = x; rect.right = x + width; rect.top = y; diff --git a/src/uxa/uxa-accel.c b/src/uxa/uxa-accel.c index e456e6c..8c4193e 100644 --- a/src/uxa/uxa-accel.c +++ b/src/uxa/uxa-accel.c @@ -34,6 +34,8 @@ #include "uxa.h" #include "mipict.h" +extern int g_in_composite; + static CARD32 format_for_depth(int depth) { @@ -105,6 +107,7 @@ uxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, if (!uxa_screen->info->check_composite(PictOpSrc, src, NULL, dst, 0, 0)) { FreePicture(src, 0); FreePicture(dst, 0); + g_in_composite = 1; goto solid; } @@ -263,10 +266,12 @@ solid: } (*uxa_screen->info->done_solid) (dst_pixmap); + g_in_composite = 0; return; fallback: uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted); + g_in_composite = 0; } static Bool @@ -1072,6 +1077,7 @@ try_solid: extents->y2 - extents->y1)) { FreePicture(src, 0); FreePicture(dst, 0); + g_in_composite = 1; goto try_solid; } @@ -1118,6 +1124,7 @@ try_solid: err: REGION_TRANSLATE(screen, pRegion, -xoff, -yoff); + g_in_composite = 0; return ret; } diff --git a/src/uxa/uxa-glyphs.c b/src/uxa/uxa-glyphs.c index dd50dfc..8b4b92c 100644 --- a/src/uxa/uxa-glyphs.c +++ b/src/uxa/uxa-glyphs.c @@ -68,6 +68,8 @@ #include "mipict.h" +extern int g_in_composite; + /* Width of the pixmaps we use for the caches; this should be less than * max texture size of the driver; this may need to actually come from * the driver. @@ -1045,12 +1047,14 @@ uxa_glyphs(CARD8 op, pDst->alphaMap || pSrc->alphaMap) { fallback: uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + g_in_composite = 0; return; } /* basic sanity check */ if (uxa_screen->info->check_composite && !uxa_screen->info->check_composite(op, pSrc, NULL, pDst, 0, 0)) { + g_in_composite = 1; goto fallback; } diff --git a/src/uxa/uxa-render.c b/src/uxa/uxa-render.c index ac80c45..2ae4629 100644 --- a/src/uxa/uxa-render.c +++ b/src/uxa/uxa-render.c @@ -34,6 +34,8 @@ #ifdef RENDER #include "mipict.h" +extern int g_in_composite; + static void uxa_composite_fallback_pict_desc(PicturePtr pict, char *string, int n) { @@ -1023,6 +1025,7 @@ try_solid: extents->y2 - extents->y1)) { if (op == PictOpSrc || op == PictOpClear) { FreePicture(src, 0); + g_in_composite = 1; goto try_solid; } @@ -1062,6 +1065,7 @@ try_solid: } pixman_region_fini(®ion); + g_in_composite = 0; return; err_src: @@ -1070,6 +1074,7 @@ err_region: pixman_region_fini(®ion); fallback: uxa_screen->SavedCompositeRects(op, dst, color, num_rects, rects); + g_in_composite = 0; } static int @@ -1603,6 +1608,8 @@ uxa_composite(CARD8 op, goto done; } + g_in_composite = 1; + /* Now see if we can use * uxa_fill_region_tiled() */ @@ -1655,6 +1662,7 @@ uxa_composite(CARD8 op, if (ret == 1) goto done; + g_in_composite = 1; /* For generic masks and solid src pictures, mach64 can do * Over in two passes, similar to the component-alpha case. */ @@ -1698,6 +1706,7 @@ done: pSrc->repeat = saveSrcRepeat; if (pMask) pMask->repeat = saveMaskRepeat; + g_in_composite = 0; } #endif diff --git a/src/uxa/uxa-unaccel.c b/src/uxa/uxa-unaccel.c index f3539da..d49d127 100644 --- a/src/uxa/uxa-unaccel.c +++ b/src/uxa/uxa-unaccel.c @@ -411,6 +411,12 @@ uxa_check_get_spans(DrawablePtr pDrawable, } } +int g_in_composite = 0; +int uxa_in_composite(void) +{ + return g_in_composite; +} + void uxa_check_composite(CARD8 op, PicturePtr pSrc, @@ -442,11 +448,13 @@ uxa_check_composite(CARD8 op, if (!pMask || pMask->pDrawable == NULL || uxa_prepare_access(pMask->pDrawable, NULL, UXA_ACCESS_RO)) { + g_in_composite = 1; fbComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); + g_in_composite = 0; if (pMask && pMask->pDrawable != NULL) uxa_finish_access(pMask->pDrawable); }
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel