c++ - Optimizing loop that has QString manipulations -


in project, wrote function decompress qstring compressed using basic compression format wrote in seperate function. after testing, i've found function thing causing massive slowdowns since run on huge qstring's , called on 2900 times.

i've been trying change function runs faster. i've dabbled qstringref's no results (i might have done wrong). qbytearrays , qbyterefs hard work , check values (imo).

i really need optimizing function runs fast! fast possible! believe constant calling of .mid slowing things down, don't know other way read/write bytes.

edit: better question, there common practice i'm missing when come decompression functions? use zlib later in same program , compresses faster simple function wrote below. why that? zlib differently?

thanks time in advance. :)


here very small compressed qstring like:

//compressed //this qstring hexadecimal representation of qbytearray // qstring com("010203ff0504ff0a05ff00ff01ff02ff0306); 

and, here same qstring after decompression:

//decompressed qstring decom("0102030404040404040505050505050505050505ffffffffffff06060606); 

sorry if don't understand format right away... doesn't matter much. maybe helps:

-a byte "ff" tells we're decompress -the byte after "ff" number of times repeat next byte + 1 -unless number 0, 1, or 2, "ff" value repeated  examples: -"010203" decompressed "010203"  -"ff0401" decompressed "0101010101"  -"ff02" decompressed "ffffff" 

this decompression function wrote:

int hextoints(qstring num_hex)  //converts byte number {     uint num_uint;     bool ok;     num_uint = num_hex.touint(&ok,16);     return (int)num_uint; } void decompress(qstring com, qstring &decom) {     qstring c;                 //current byte     qstring n;                 //new/next byte     int bytepos(0);            //current position in qstring     int byterepeat;            //number of times repeat byte n      c = com.mid(bytepos, 2);   //get first byte (01)     decom.clear();             //clear decom in case had values prior          {         bytepos = bytepos + 2;      //move current position next byte         if(c == "ff")               //is decompression happening?         {             c = com.mid(bytepos, 2);   //current byte "next" byte             byterepeat = hextoints(c); //c tells how many times next byte needs repeated              if(byterepeat <= 2)        //if c's value <= 2... ff value             {                 n = "ff";              //new byte ff                 bytepos = bytepos + 2; //update current position             }             else                       //if not, c number of times next byte should appended             {                 n = com.mid(bytepos + 2, 2); //new byte next byte                 bytepos = bytepos + 4;       //update current position             }              for(int j = 0; j<=byterepeat; j++)//append n correct number of times                 decom.append(n);         }         else                   //guess we're not decompressing, append c             decom.append(c);         c = com.mid(bytepos, 2);   //get new current byte     }while(bytepos < com.length());  //stop when bytes read } 

current optimized function based on comments: (5%-10% faster in debug mode only)

void decompress2(const qstring com, qstring &decom) {     qstringref c;     qstring n;     int bytepos(0);     int byterepeat;      c = com.midref(bytepos, 2);     decom.clear();          {         bytepos = bytepos + 2;         if(c == "ff")         {             c = com.midref(bytepos, 2);             byterepeat = c.tostring().toint(0,16);              if(byterepeat <= 2)             {                 n = "ff";                 bytepos = bytepos + 2;             }             else             {                 n = com.mid(bytepos + 2, 2);                 bytepos = bytepos + 4;             }              for(int j = 0; j<=byterepeat; j++)                 decom.append(n);         }         else             decom.append(c);         c = com.midref(bytepos, 2);     }while(bytepos < com.length()); } 

you shouldn't treating array of bytes string. that's silly , noted, dead slow. use raw byte values instead , operate on them.

i know shouldn't writing code other people, had absolutely nothing better do, here in straight c++. know you're using qt , i'm of below code has equivalent in terms of qt's bytearray, that's can figure out then, if pure c++ not option.

#include <vector> #include <cstdint> #include <iomanip> #include <iostream>  std::vector<std::uint8_t> decompress(const std::vector<std::uint8_t>& com) {   std::vector<std::uint8_t> decom;   decom.reserve(com.size()); // conservative estimate of required size    for(auto = begin(com); != end(com); ++it)   {     if(*it == 0xff)     {       ++it;       if(it != end(com))       {         std::uint8_t number_of_repeats = *it;         if(number_of_repeats <= 2)         {           std::fill_n(std::back_inserter(decom), number_of_repeats, 0xff);           continue;         }         else         {           ++it;           if(it != end(com))             std::fill_n(std::back_inserter(decom), number_of_repeats, *it);           else             throw 42; // handle error in way         }       }       else          throw 42; // handle error in way     }     else       decom.push_back(*it);   }   return decom; } int main() {   std::vector<std::uint8_t> com{0x01, 0x02, 0x03, 0xff, 0x05, 0x04, 0xff, 0x0a, 0x05, 0xff, 0x00, 0xff, 0x01, 0xff, 0x02, 0xff, 0x03, 0x06};     for(const auto& value : com)     std::cout << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned short>(value) << ' ';   std::cout << '\n';   auto result = decompress(com);    for(const auto& value : result)     std::cout << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned short>(value) << ' '; } 

live demo here. take no responsibility respect correctness, efficiency or otherwise usability of code. written in under 5 minutes.

note believe decompressed string in long example wrong. according rules, should be

01 02 03 04 04 04 04 04 05 05 05 05 05 05 05 05 05 05 ff ff ff 06 06 06 

starting 06 repeated 3 times, 2 times ff, 1 time ff 0 times ff, rest.


Comments

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - Bypass Geo Redirect for specific directories -

php - .htaccess mod_rewrite for dynamic url which has domain names -