Performance vs. Design (long)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Case

    #1

    Performance vs. Design (long)

    I've had some discussions with colleagues about the
    API of a module for sending/receiving messages on a
    network connection.

    On both ends are different applications, each having
    their own internal way of storing the data which has
    to be communicated (using a common data protocol).

    I proposed to use a common interface, having the face
    of the network data protocol (XYZ). Many fields in the
    protocol message are optional. I proposed to use a
    bit-field structure. To prevent one extra copy of
    large chucks of data, I proposed to use pointers.

    typedef struct
    {
    unsigned int number1 : 1;
    unsigned int number2 : 1;
    unsigned int much_data : 8; /* > 0 means length */
    } XYZ_ind;

    typedef struct
    {
    int number1;
    int number2;
    char *much_data;
    XYX_ind_t ind;
    } XYZ_data_t;

    void XYZ_send(XYZ_da ta_t *data); /* encodes, then sends */

    The receiving side uses a callback, with similar prototype.

    Both sides will now have to convert their own internal format
    to a XYZ_data_t structure. This creates a clea[n|r] interface,
    making the XYZ module independent of either side.


    The 'opposing' idea is to not specify a common interface for
    all users. So, no XYZ_data_t. Instead of one shared XYZ_send(),
    there will be two: A_send(A_data_t *) and B_send(B_data *).
    Instead of one module, there will be three.

    The only advantage above having a real interface, is performance:
    no conversion between internal format to XYZ_data_t (which is not
    much more than assignments). The A_send() and B_send() will both
    encode the message in their own way, and right away.


    Yes, we are working on time-critical stuff, but I have the feeling
    that this second approach falls in the 97% of the 'premature opti-
    mization, being the root of all evil'. I estimated that the clean
    interface may add about 1/1000 to the execution time.

    Any thoughts on this issue?

    Case

  • CBFalconer

    #2
    Re: Performance vs. Design (long)

    Case wrote:[color=blue]
    >
    > I've had some discussions with colleagues about the
    > API of a module for sending/receiving messages on a
    > network connection.
    >
    > On both ends are different applications, each having
    > their own internal way of storing the data which has
    > to be communicated (using a common data protocol).
    >
    > I proposed to use a common interface, having the face
    > of the network data protocol (XYZ). Many fields in the
    > protocol message are optional. I proposed to use a
    > bit-field structure. To prevent one extra copy of
    > large chucks of data, I proposed to use pointers.
    >
    > typedef struct
    > {
    > unsigned int number1 : 1;
    > unsigned int number2 : 1;
    > unsigned int much_data : 8; /* > 0 means length */
    > } XYZ_ind;
    >[/color]
    .... snip ...[color=blue]
    > mization, being the root of all evil'. I estimated that the
    > clean interface may add about 1/1000 to the execution time.
    >
    > Any thoughts on this issue?[/color]

    What clean interface? One bit numbers don't carry much
    information, and I have a tough time envisioning much_data crammed
    into 8 bits. Also, bit fields are inherently non-portable, even
    between generations of the same compiler on the same hardware.

    --
    Chuck F (cbfalconer@yah oo.com) (cbfalconer@wor ldnet.att.net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home .att.net> USE worldnet address!


    Comment

    • Case

      #3
      Re: Performance vs. Design (long)

      CBFalconer wrote:[color=blue]
      > Case wrote:
      >[color=green]
      >>I've had some discussions with colleagues about the
      >>API of a module for sending/receiving messages on a
      >>network connection.
      >>
      >>On both ends are different applications, each having
      >>their own internal way of storing the data which has
      >>to be communicated (using a common data protocol).
      >>
      >>I proposed to use a common interface, having the face
      >>of the network data protocol (XYZ). Many fields in the
      >>protocol message are optional. I proposed to use a
      >>bit-field structure. To prevent one extra copy of
      >>large chucks of data, I proposed to use pointers.
      >>
      >>typedef struct
      >>{
      >> unsigned int number1 : 1;
      >> unsigned int number2 : 1;
      >> unsigned int much_data : 8; /* > 0 means length */
      >>} XYZ_ind;
      >>[/color]
      >
      > ... snip ...
      >[color=green]
      >>mization, being the root of all evil'. I estimated that the
      >>clean interface may add about 1/1000 to the execution time.
      >>
      >>Any thoughts on this issue?[/color]
      >
      >
      > What clean interface? One bit numbers don't carry much
      > information, and I have a tough time envisioning much_data crammed
      > into 8 bits. Also, bit fields are inherently non-portable, even
      > between generations of the same compiler on the same hardware.
      >[/color]

      XYZ_ind contains presence/length indicators for the actual
      structure members, which have the same name.

      Case

      Comment

      • Dan Pop

        #4
        Re: Performance vs. Design (long)

        In <40DADA37.5EF77 D5A@yahoo.com> CBFalconer <cbfalconer@yah oo.com> writes:
        [color=blue]
        >into 8 bits. Also, bit fields are inherently non-portable, even[/color]
        ^^^^[color=blue]
        >between generations of the same compiler on the same hardware.[/color]
        ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^
        Care to provide a couple of concrete examples? I have a hard time
        imagining an implementor screwing his user base...

        Dan
        --
        Dan Pop
        DESY Zeuthen, RZ group
        Email: Dan.Pop@ifh.de

        Comment

        • Alan Balmer

          #5
          Re: Performance vs. Design (long)

          On Thu, 24 Jun 2004 13:26:24 +0200, Case <no@no.no> wrote:
          [color=blue]
          >I've had some discussions with colleagues about the
          >API of a module for sending/receiving messages on a
          >network connection.
          >
          >On both ends are different applications, each having
          >their own internal way of storing the data which has
          >to be communicated (using a common data protocol).
          >
          >I proposed to use a common interface, having the face
          >of the network data protocol (XYZ). Many fields in the
          >protocol message are optional. I proposed to use a
          >bit-field structure. To prevent one extra copy of
          >large chucks of data, I proposed to use pointers.
          >
          >typedef struct
          >{
          > unsigned int number1 : 1;
          > unsigned int number2 : 1;
          > unsigned int much_data : 8; /* > 0 means length */
          >} XYZ_ind;
          >
          >typedef struct
          >{
          > int number1;
          > int number2;
          > char *much_data;
          > XYX_ind_t ind;
          >} XYZ_data_t;
          >
          >void XYZ_send(XYZ_da ta_t *data); /* encodes, then sends */
          >[/color]
          I wouldn't use the bit fields. Aside from their portability problems,
          they will probably be less efficient - the transmission time saved
          will be less than the additional processing time.
          [OT]
          Communications protocols typically send the message size first, making
          it easy to grab the entire message in two reads, and making it easy to
          send variable size messages, or change your mind about the message
          size.
          I assume that your send routine is sending the data that much_data
          points to, not the pointer itself.
          [color=blue]
          >The receiving side uses a callback, with similar prototype.
          >
          >Both sides will now have to convert their own internal format
          >to a XYZ_data_t structure. This creates a clea[n|r] interface,
          >making the XYZ module independent of either side.
          >
          >
          >The 'opposing' idea is to not specify a common interface for
          >all users. So, no XYZ_data_t. Instead of one shared XYZ_send(),
          >there will be two: A_send(A_data_t *) and B_send(B_data *).
          >Instead of one module, there will be three.
          >
          >The only advantage above having a real interface, is performance:
          >no conversion between internal format to XYZ_data_t (which is not
          >much more than assignments). The A_send() and B_send() will both
          >encode the message in their own way, and right away.
          >
          >
          >Yes, we are working on time-critical stuff, but I have the feeling
          >that this second approach falls in the 97% of the 'premature opti-
          >mization, being the root of all evil'. I estimated that the clean
          >interface may add about 1/1000 to the execution time.
          >
          >Any thoughts on this issue?
          >
          >Case[/color]

          --
          Al Balmer
          Balmer Consulting
          removebalmercon sultingthis@att .net

          Comment

          • Case -

            #6
            Re: Performance vs. Design (long)

            Alan Balmer wrote:[color=blue]
            > On Thu, 24 Jun 2004 13:26:24 +0200, Case <no@no.no> wrote:[color=green]
            >>I've had some discussions with colleagues about the
            >>API of a module for sending/receiving messages on a
            >>network connection.
            >>
            >>On both ends are different applications, each having
            >>their own internal way of storing the data which has
            >>to be communicated (using a common data protocol).
            >>
            >>I proposed to use a common interface, having the face
            >>of the network data protocol (XYZ). Many fields in the
            >>protocol message are optional. I proposed to use a
            >>bit-field structure. To prevent one extra copy of
            >>large chucks of data, I proposed to use pointers.
            >>
            >>typedef struct
            >>{
            >> unsigned int number1 : 1;
            >> unsigned int number2 : 1;
            >> unsigned int much_data : 8; /* > 0 means length */
            >>} XYZ_ind;
            >>
            >>typedef struct
            >>{
            >> int number1;
            >> int number2;
            >> char *much_data;
            >> XYX_ind_t ind;
            >>} XYZ_data_t;
            >>
            >>void XYZ_send(XYZ_da ta_t *data); /* encodes, then sends */
            >>[/color]
            >
            > I wouldn't use the bit fields. Aside from their portability problems,
            > they will probably be less efficient - the transmission time saved
            > will be less than the additional processing time.
            > [OT]
            > Communications protocols typically send the message size first, making
            > it easy to grab the entire message in two reads, and making it easy to
            > send variable size messages, or change your mind about the message
            > size.
            > I assume that your send routine is sending the data that much_data
            > points to, not the pointer itself.[/color]

            I think I am so much in this design, that I forgot to
            mention essentials for understanding it for outsiders.
            Sorry about this people. I don't send the XYZ_ind_t
            field, which is only used to indicate which fields of
            the actual data in the rest of the struct needs to be
            send.

            I decided to use bit-fields because of their small size
            compared to using a set of booleans (i.e., int's). This
            is because I need to initializa all indicators to 0;
            again a matter of performance. In my real aplication
            there are about 40 optional fields, of which less than
            half are actually being used on average.

            In my view, bit-fields are not that performance demanding
            compared to using int's set to 0 or 1. What do you think?

            Case

            Comment

            • Arthur J. O'Dwyer

              #7
              Re: Performance vs. Design (long)


              On Thu, 24 Jun 2004, Case - wrote:[color=blue][color=green][color=darkred]
              > >>
              > >>typedef struct
              > >>{
              > >> unsigned int number1 : 1;
              > >> unsigned int number2 : 1;
              > >> unsigned int much_data : 8; /* > 0 means length */
              > >>} XYZ_ind;[/color]
              > >
              > > I wouldn't use the bit fields.[/color][/color]
              [...][color=blue]
              > I decided to use bit-fields because of their small size
              > compared to using a set of booleans (i.e., int's). This
              > is because I need to initializa all indicators to 0;
              > again a matter of performance. In my real aplication
              > there are about 40 optional fields, of which less than
              > half are actually being used on average.
              >
              > In my view, bit-fields are not that performance demanding
              > compared to using int's set to 0 or 1. What do you think?[/color]

              I would use a set of flags, myself.

              struct XYZ_ind
              {
              unsigned long fields;
              int much_data;
              };

              #define FIELD_NUMBER1 0x0001
              #define FIELD_NUMBER2 0x0002
              #define FIELD_FOO 0x0004
              [...]

              Then instead of 'if (x->number1)' you would write
              'if (x->fields & FIELD_NUMBER1)' . Extra typing, but guaranteed to
              be small (unlike bit-fields, AFAIK) and pretty fast in practice.
              And bitwise flags are IMHO less obscure than bit-fields, although
              you could argue both ways, I suppose.

              And of course initializing all your flags to zero becomes a single
              assignment, instead of 32 assignments. That's a plus.

              If you need more than 32 flags, just add a 'fields2' member to
              your struct. If it sounds reasonable, you might segregate the
              flags by purpose, e.g.

              unsigned int header_flags;
              unsigned int encoding_flags;
              unsigned int message_flags;
              unsigned int network_flags;
              [...]

              HTH,
              -Arthur

              Comment

              • Christian Bau

                #8
                Re: Performance vs. Design (long)

                In article <40db244b$0$623 99$5fc3050@drea der2.news.tisca li.nl>,
                Case - <no@no.no> wrote:
                [color=blue]
                > I decided to use bit-fields because of their small size
                > compared to using a set of booleans (i.e., int's). This
                > is because I need to initializa all indicators to 0;
                > again a matter of performance. In my real aplication
                > there are about 40 optional fields, of which less than
                > half are actually being used on average.
                >
                > In my view, bit-fields are not that performance demanding
                > compared to using int's set to 0 or 1. What do you think?[/color]

                Bit fields are inherently non-portable. To maximise portability, send a
                sequence of unsigned char values with values from 0 to 255. Instead of
                bit-fields, use the eight bits in the unsigned char.

                Otherwise, at the very least you will end up having to define your
                structs in different ways depending on the compiler.

                Comment

                • Travis Breitkreutz

                  #9
                  Re: Performance vs. Design (long)

                  "Case -" <no@no.no> wrote in message
                  news:40db244b$0 $62399$5fc3050@ dreader2.news.t iscali.nl...[color=blue]
                  > Alan Balmer wrote:[color=green]
                  > > On Thu, 24 Jun 2004 13:26:24 +0200, Case <no@no.no> wrote:[color=darkred]
                  > >>I've had some discussions with colleagues about the
                  > >>API of a module for sending/receiving messages on a
                  > >>network connection.
                  > >>
                  > >>On both ends are different applications, each having
                  > >>their own internal way of storing the data which has
                  > >>to be communicated (using a common data protocol).
                  > >>
                  > >>I proposed to use a common interface, having the face
                  > >>of the network data protocol (XYZ). Many fields in the
                  > >>protocol message are optional. I proposed to use a
                  > >>bit-field structure. To prevent one extra copy of
                  > >>large chucks of data, I proposed to use pointers.
                  > >>
                  > >>typedef struct
                  > >>{
                  > >> unsigned int number1 : 1;
                  > >> unsigned int number2 : 1;
                  > >> unsigned int much_data : 8; /* > 0 means length */
                  > >>} XYZ_ind;
                  > >>
                  > >>typedef struct
                  > >>{
                  > >> int number1;
                  > >> int number2;
                  > >> char *much_data;
                  > >> XYX_ind_t ind;
                  > >>} XYZ_data_t;
                  > >>
                  > >>void XYZ_send(XYZ_da ta_t *data); /* encodes, then sends */
                  > >>[/color]
                  > >
                  > > I wouldn't use the bit fields. Aside from their portability[/color][/color]
                  problems,[color=blue][color=green]
                  > > they will probably be less efficient - the transmission time saved
                  > > will be less than the additional processing time.
                  > > [OT]
                  > > Communications protocols typically send the message size first,[/color][/color]
                  making[color=blue][color=green]
                  > > it easy to grab the entire message in two reads, and making it easy[/color][/color]
                  to[color=blue][color=green]
                  > > send variable size messages, or change your mind about the message
                  > > size.
                  > > I assume that your send routine is sending the data that much_data
                  > > points to, not the pointer itself.[/color]
                  >
                  > I think I am so much in this design, that I forgot to
                  > mention essentials for understanding it for outsiders.
                  > Sorry about this people. I don't send the XYZ_ind_t
                  > field, which is only used to indicate which fields of
                  > the actual data in the rest of the struct needs to be
                  > send.
                  >
                  > I decided to use bit-fields because of their small size
                  > compared to using a set of booleans (i.e., int's). This
                  > is because I need to initializa all indicators to 0;
                  > again a matter of performance. In my real aplication
                  > there are about 40 optional fields, of which less than
                  > half are actually being used on average.
                  >
                  > In my view, bit-fields are not that performance demanding
                  > compared to using int's set to 0 or 1. What do you think?
                  >[/color]
                  It depends upon the processor. Some processors have built-in
                  bit-handling instructions; some do not. Most mid- to high-range
                  processors handle ints much more efficiently than they handle individual
                  bits.

                  Travis


                  Comment

                  • Felipe Magno de Almeida

                    #10
                    Re: Performance vs. Design (long)

                    I would use flags either.
                    --
                    Felipe Magno de Almeida
                    Ciencia da Computacao - Unicamp
                    felipe.almeida@ ic.unicamp.br - UIN: 146989862
                    Cause Rock and Roll can never die.
                    "if you want to learn something really well, teach it to a computer."
                    What is Communism?
                    Answer: "Communism is the doctrine of the conditions of the liberation
                    of the proletariat." (by Karl Marx)

                    Comment

                    Working...