В моем проекте я написал функцию для распаковки QString, которая сжата с использованием очень простого формата сжатия, который я написал в отдельной функции. Но после некоторого тестирования я обнаружил, что эта функция вызывает массовые замедления, поскольку она запускается на огромных QString и вызывается более 2900 раз.
Я пытался изменить эту функцию, чтобы она работала быстрее. Я баловался с QStringRef без хороших результатов (возможно, я сделал это неправильно). С QByteArrays и QByteRefs сложно работать и проверять значения (imo).
Мне действительно нужна помощь в оптимизации этой функции, чтобы она работала БЫСТРО! Как можно быстрее! Я считаю, что постоянный вызов .mid замедляет работу, но я просто не знаю другого способа читать/записывать байты.
РЕДАКТИРОВАТЬ: Лучший вопрос, есть ли обычная практика, которую я пропускаю, когда дело доходит до функций декомпрессии? Я использую zlib позже в этой же программе, и она сжимает быстрее, чем эта простая функция, которую я написал ниже. Почему это? Что zlib делает по-другому?
Спасибо за ваше время заранее. :)
Вот как будет выглядеть очень маленькая сжатая строка QString:
//Compressed
//This QString is just a hexadecimal representation of a QByteArray
//
QString com("010203ff0504ff0a05ff00ff01ff02ff0306);
А вот каким будет тот же QString после распаковки:
//Decompressed
QString decom("0102030404040404040505050505050505050505ffffffffffff06060606);
Извините, если вы не сразу поняли формат... это не имеет большого значения. Возможно, это поможет:
-a byte with "ff" tells us we're about to decompress
-the byte after "ff" is the number of times to repeat the NEXT byte + 1
-UNLESS that number is 0, 1, or 2, then "ff" is the value to be repeated
Examples:
-"010203" decompressed is "010203"
-"ff0401" decompressed is "0101010101"
-"ff02" decompressed is "ffffff"
Это функция декомпрессии, которую я написал:
int HexToIntS(QString num_hex) //converts the byte to a 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 to repeat byte n
c = com.mid(bytePos, 2); //get first byte (01)
decom.clear(); //clear decom just in case it had values prior
do
{
bytePos = bytePos + 2; //move the current position to the next byte
if(c == "ff") //is decompression happening?
{
c = com.mid(bytePos, 2); //current byte is now the "next" byte
byteRepeat = HexToIntS(c); //c tells us how many times the NEXT byte needs to be repeated
if(byteRepeat <= 2) //if c's value is <= 2... then ff is the value
{
n = "ff"; //new byte is just ff
bytePos = bytePos + 2; //update the current position
}
else //if not, then c is the number of times the NEXT byte should be appended
{
n = com.mid(bytePos + 2, 2); //new byte is the NEXT byte
bytePos = bytePos + 4; //update the current position
}
for(int j = 0; j<=byteRepeat; j++)//append n the correct number of times
decom.append(n);
}
else //guess we're not decompressing, so just append c
decom.append(c);
c = com.mid(bytePos, 2); //get the new current byte
}while(bytePos < com.length()); //stop when all bytes were read
}
Текущая оптимизированная функция на основе ваших комментариев: (на 5%-10% быстрее только в режиме отладки)
void Decompress2(const QString com, QString &decom)
{
QStringRef c;
QString n;
int bytePos(0);
int byteRepeat;
c = com.midRef(bytePos, 2);
decom.clear();
do
{
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());
}