[Xcb] Question: Why are structs not serialized elementwise in the autogenerated C cocde?

Christoph Reimann chrr at arcor.de
Wed Jun 9 14:41:14 PDT 2010


Hi & thanks again for the advice!

> I suspect it was never done this way for performance reasons. Larger
> iovecs mean more dcache usage, more setting means more icache usage, and
> processing all the extra elements means more CPU usage.
>
> That said, I doubt anyone has ever measured the difference. Perhaps you
> could measure and let us know.
>

I did 10.000 xcb_create_window() calls with current libxcb and
modified (see below [0] for the generated code) - after running it for
several times, there seems to be no difference considering the
accuracy of 'time', conforming with Jamey's post (the tests did some
harm to my X server though - Xorg is keeping my CPU quite busy now and
my legs warm...):

latest libxcb-git
real	0m2.334s
user	0m0.080s
sys	0m0.300s

modified libxcb:
real	0m2.235s
user	0m0.100s
sys	0m0.330s

> Alternatively, you could automatically join adjacent fields where
> possible, allowing you to insert variable fields without changing the
> output in the case where there are no variable fields. I'm not sure how
> much code would be needed to do that in c_client.py.
>

Not sure if I got this right - do you suggest serializing only those
structs elemtent-wise where fixed- and variable-sized fields are
mixed? (Which would be no problem in c_client.py.)
By serializing everything field-wise I can now (in theory as untested)
handle protocol definitions that include things like lists of variable
sized members and mixed variable/fixed types - at the expense of
increased autogenerated code base:

xproto.c: 14471 lines
modified xproto.c: 17061 lines

So anyway - for the code in c_client.py it is somewhat simpler to
handle the serializing consistently - but then the code changes amount
only to about 80 lines.

> That said, I'd be much happier if all padding was explicitly specified
> in the .xml files, and none was ever automagically inserted by any of
> the generators. See, for example, commit 0d62c1d0 (and surrounding
> commit series) where we added some of the missing padding. It wouldn't
> surprise me to discover that we'd missed some.

Again unsure if I understood correctly (sorry :) - if the xml spec
would contain the padding, then I should be able to calculate in
c_client.py (by simply adding up the sizes of the fixed fields)
whether the specified padding is complete?

Have a nice evening,

Christoph


[0] modified xcb_create_window request:

xcb_void_cookie_t
xcb_create_window (xcb_connection_t *c  /**< */,
                   uint8_t           depth  /**< */,
                   xcb_window_t      wid  /**< */,
                   xcb_window_t      parent  /**< */,
                   int16_t           x  /**< */,
                   int16_t           y  /**< */,
                   uint16_t          width  /**< */,
                   uint16_t          height  /**< */,
                   uint16_t          border_width  /**< */,
                   uint16_t          _class  /**< */,
                   xcb_visualid_t    visual  /**< */,
                   uint32_t          value_mask  /**< */,
                   const uint32_t   *value_list  /**< */)
{
    unsigned int xcb_unpadded = 0;
    static const xcb_protocol_request_t xcb_req = {
        /* count */ 14,
        /* ext */ 0,
        /* opcode */ XCB_CREATE_WINDOW,
        /* isvoid */ 1
    };

    struct iovec xcb_parts[16];
    xcb_void_cookie_t xcb_ret;

    /* xcb_create_window_request_t.depth */
    xcb_parts[2].iov_base = (char *) &depth;
    xcb_parts[2].iov_len  = sizeof(uint8_t);
    xcb_unpadded += sizeof(uint8_t);
    /* xcb_create_window_request_t.wid */
    xcb_parts[3].iov_base = (char *) &wid;
    xcb_parts[3].iov_len  = sizeof(xcb_window_t);
    xcb_unpadded += sizeof(xcb_window_t);
    /* xcb_create_window_request_t.parent */
    xcb_parts[4].iov_base = (char *) &parent;
    xcb_parts[4].iov_len  = sizeof(xcb_window_t);
    xcb_unpadded += sizeof(xcb_window_t);
    /* xcb_create_window_request_t.x */
    xcb_parts[5].iov_base = (char *) &x;
    xcb_parts[5].iov_len  = sizeof(int16_t);
    xcb_unpadded += sizeof(int16_t);
    /* xcb_create_window_request_t.y */
    xcb_parts[6].iov_base = (char *) &y;
    xcb_parts[6].iov_len  = sizeof(int16_t);
    xcb_unpadded += sizeof(int16_t);
    /* xcb_create_window_request_t.width */
    xcb_parts[7].iov_base = (char *) &width;
    xcb_parts[7].iov_len  = sizeof(uint16_t);
    xcb_unpadded += sizeof(uint16_t);
    /* xcb_create_window_request_t.height */
    xcb_parts[8].iov_base = (char *) &height;
    xcb_parts[8].iov_len  = sizeof(uint16_t);
    xcb_unpadded += sizeof(uint16_t);
    /* xcb_create_window_request_t.border_width */
    xcb_parts[9].iov_base = (char *) &border_width;
    xcb_parts[9].iov_len  = sizeof(uint16_t);
    xcb_unpadded += sizeof(uint16_t);
    /* xcb_create_window_request_t._class */
    xcb_parts[10].iov_base = (char *) &_class;
    xcb_parts[10].iov_len  = sizeof(uint16_t);
    xcb_unpadded += sizeof(uint16_t);
    /* xcb_create_window_request_t.visual */
    xcb_parts[11].iov_base = (char *) &visual;
    xcb_parts[11].iov_len  = sizeof(xcb_visualid_t);
    xcb_unpadded += sizeof(xcb_visualid_t);
    /* xcb_create_window_request_t.value_mask */
    xcb_parts[12].iov_base = (char *) &value_mask;
    xcb_parts[12].iov_len  = sizeof(uint32_t);
    xcb_unpadded += sizeof(uint32_t);
    xcb_parts[13].iov_base = 0;
    xcb_parts[13].iov_len = -xcb_unpadded & 3;
    /* value_list */
    xcb_parts[14].iov_base = (char *) value_list;
    xcb_parts[14].iov_len  = xcb_popcount(value_mask) * sizeof(uint32_t);
    xcb_unpadded = xcb_parts[14].iov_len;
    xcb_parts[15].iov_base = 0;
    xcb_parts[15].iov_len = -xcb_unpadded & 3;

    xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
    return xcb_ret;
}


More information about the Xcb mailing list