简体   繁体   中英

How to reduce CPU usage?

I have to decode some byte array(raw data). It can consist of basic data types(int,unsigned int,char,short etc.).According to defined structure, i need to interpret them. below is example:

struct testData
{ 
 int a;
char c;
};
   unsigned char** buf = {0x01,0x00,0x00,0x00,0x41}
   example byte array(in little endian) : 0100000041

   should give decoding like : a = 1, c = 'A'

The sample data can be very big and the sample structure( eg testData) can contain 200 - 3000 fields. If I use am casting to read the appropriate data from **buf and set pointer like below:

    int a = *(reinterpret_cast<int*>(*buf);
    *buf += 4;
    char c = **buf;
    *buf += 1;

My CPU usage is quite high if number of fileds need to be decoded are high. example:

    struct testData
    {
     int element1;
     char element2;
     int element3;
      ... ...
     ... ...
      short element200;
     char element201;
     char element202;
    }

Is there a way to reduce the CPU load as well as keep decoding very fast?

I have two constraints:

  1. "Structure can contain padding byte."
  2. I do not have control on how structure will be defined. Structure can contain nested elements as well.
int a = *(reinterpret_cast<int*>(*buf);

Don't use reinterpret_cast . You are lying to the compiler and forcing unaligned accesses. Worse, you are hiding from the compiler the very information it needs to optimize your code -- that the pointer is actually to characters. Instead, code what you mean as straightforward as possible, which is:

int a=static_cast<int>(*buf[0]) |
     (static_cast<int>(*buf[1])<<8) |
     (static_cast<int>(*buf[2])<<16) |
     (static_cast<int>(*buf[3])<<24);

This is simple, clear, and what you actually want. The compiler will have no problem optimizing it. (And, it will work regardless of your platform's endianness.)

You should be able to simply map the struct to the buffer, as long as the struct is properly packed:

#pragma pack(push, 1)
struct testData
    {
     int element1;
     char element2;
     int element3;
      ... ...
     ... ...
      short element200;
     char element201;
     char element202;
    }
#pragma pack(pop)

You should also declare the structure in a alignment sensible way, don't mix int followed by char followed by int ... Then if you read the data in an aligned buffer, a simple cast of the buffer to testData* would give you access to all members. This way you would avoid all those gratuitous copies. If you read the structure in forward fashion ( p->element1 , then read p->element2 then p->element3 and so on) hardware prefetch should kick in and give a big boost.

Further enhancements would require actual measurements of hot spots. Also, check this book out from the library and read it: The Software Optimization Cookbook .

Further to David Schwartz's response, you can tidy this up by writing some helper template functions. I'd suggest something like this (untested).

template<typename T>
const unsigned char * read_from_buffer( T* value, const unsigned char * buffer);

template<>
const unsigned char * read_from_buffer<int>( int* value, const unsigned char * buffer)
{
   *value = static_cast<int>(*buf[0]) |
     (static_cast<int>(*buf[1])<<8) |
     (static_cast<int>(*buf[2])<<16) |
     (static_cast<int>(*buf[3])<<24);
   return buffer+4'
}

template<>
const unsigned char * read_from_buffer<char>( char * value, const unsigned char * buffer )
{
  *value = *buffer;
  return buffer+1;
}

struct TestData
{
  int a;
  char c;
};

int main()
{
  unsigned char buf[] = {0x01,0x00,0x00,0x00,0x41};
  unsigned char * ptr = buf;

  TestData data;
  ptr = read_from_buffer( &data.a, ptr );
  ptr = read_from_buffer( &data.c, ptr );
}

You could encapsulate this even further and add error checking etc and you'd have a nice binary stream like interface.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM