Оптимизация Qt преобразования QByteArray

Я написал функцию для преобразования представления шестнадцатеричной строки (например, x00) некоторых двоичных данных в сами данные.

Как улучшить этот код?

QByteArray restoreData(const QByteArray &data, const QString prepender = "x")
{
    QByteArray restoredData = data;

    return QByteArray::fromHex(restoredData.replace(prepender, ""));
}

person Sylva1n    schedule 24.05.2014    source источник


Ответы (2)


Как улучшить этот код?

Сравните перед оптимизацией. Не выполняйте преждевременную оптимизацию.

Помимо основного вопроса: почему вы хотите его оптимизировать?

1) Если вы действительно так обеспокоены производительностью, когда этот незначительный код с точки зрения производительности имеет значение, вы бы не использовали Qt в первую очередь, потому что Qt по своей природе медленный по сравнению с хорошо оптимизированным фреймворком.

2) Если вас не беспокоит производительность, то вы должны помнить о читабельности и обслуживании в качестве основного принципа, и в этом случае ваш код в порядке.

Вы также не показали ни одного примера из реального мира, почему именно вы хотите оптимизировать. Это похоже на академический вопрос, не имеющий для меня особой практической пользы. Было бы интересно узнать больше о мотивации.

При этом в вашем коде можно было бы сделать несколько элементов улучшения, которые также являются оптимизацией, но опять же: это делается не для оптимизации, а скорее по логическим причинам.

1) Prepender - дурная слава; в английском языке его обычно называют «префиксом».

2) Вы хотите использовать QChar вместо QString для символа.

3) Точно так же для замены вы хотите использовать '', а не строковую формулу "".

4) Я бы передал такие классы со ссылкой, а не семантикой значений, даже если это CoW (неявно совместно используемое).

5) Я бы даже не использовал здесь аргумент для префикса, поскольку он всегда один и тот же, поэтому он не совсем подходит под определение переменной.

6) Нет необходимости явно создавать промежуточную переменную.

7) Сделайте функцию встроенной.

Следовательно, вы бы написали что-то вроде этого:

QByteArray restoreData(QByteArray data)
{
    return QByteArray::fromHex(data.replace('x', ''));
}
person lpapp    schedule 24.05.2014
comment
Вы также можете выбрать метод remove(QChar) для удобства, как в QString. Это даже сделало бы код более логичным, так как вы не заменяете, а удаляете в принципе. - person lpapp; 24.05.2014

У вашего кода проблемы с производительностью из-за replace(). Сама замена не очень быстрая, а создание промежуточного объекта QByteArray еще больше замедляет код. Если вас действительно беспокоит производительность, вы можете скопировать QByteArray::fromHex реализацию из исходников Qt и изменить ее под свои нужды. К счастью, его реализация вполне автономна. Я только изменил / 2 на / 3 и добавил строку --i, чтобы пропустить символы "x".

QByteArray myFromHex(const QByteArray &hexEncoded)
{
    QByteArray res((hexEncoded.size() + 1)/ 3, Qt::Uninitialized);
    uchar *result = (uchar *)res.data() + res.size();

    bool odd_digit = true;
    for (int i = hexEncoded.size() - 1; i >= 0; --i) {
        int ch = hexEncoded.at(i);
        int tmp;
        if (ch >= '0' && ch <= '9')
            tmp = ch - '0';
        else if (ch >= 'a' && ch <= 'f')
            tmp = ch - 'a' + 10;
        else if (ch >= 'A' && ch <= 'F')
            tmp = ch - 'A' + 10;
        else
            continue;
        if (odd_digit) {
            --result;
            *result = tmp;
            odd_digit = false;
        } else {
            *result |= tmp << 4;
            odd_digit = true;
            --i;
        }
    }

    res.remove(0, result - (const uchar *)res.constData());
    return res;
}

Тест:

qDebug() << QByteArray::fromHex("54455354"); // => "TEST"
qDebug() << myFromHex("x54x45x53x54"); // => "TEST"

Этот код может вести себя неожиданно, если hexEncoded имеет неверный формат (например, "x54x45x5" будет преобразовано в "TU"). Вы можете исправить это как-то, если это проблема.

person Pavel Strakhov    schedule 24.05.2014