QByteArray: use new assign() in operator=(const char *)
operator=(~) and assign(~) share similar names but, until now, have not shared the same functionality. This patch introduces the usage of QByteArray::assign() within the non-sharing assignment operator to effectively boost efficiency by reusing the available capacity. Since these assignment operators are frequently used in many places, both within Qt and non-Qt code, this patch comes with benchmarks. The preview of the benchmark results are compared with this patch and before this patch. The findings indicate a slight enhancement in performance associated with the assignment operator. Despite the results displaying only a minor improvement, progress has been made. Therefore use assign(QByteArrayView) as replacement. (x86_64-little_endian-lp64 shared (dynamic) release build (O3); by gcc 13.2.1, endeavouros ; 13th Gen Intel(R) Core(TM) i9-13900K benchmarks executed with -perf -iterations 1000000 * The last value at the EOL represent the string size. QByteArray &operator=(const char *ch) (current) 65 cycles/iter; 317 instructions/iter; 16.0 nsec/iter (5) 71.7 cycles/iter; 383 instructions/iter; 13.0 nsec/iter (10) 59.8 cycles/iter; 318 instructions/iter; 10.9 nsec/iter (20) 70.8 cycles/iter; 340 instructions/iter; 12.9 nsec/iter (50) 80.2 cycles/iter; 419 instructions/iter; 14.6 nsec/iter (100) 164.2 cycles/iter; 899 instructions/iter; 29.9 nsec/iter (500) 260.5 cycles/iter; 1522 instructions/iter; 45.6 nsec/iter (1'000) QByteArray &operator=(const char *ch) (before) 66.8 cycles/iter; 317 instructions/iter; 16.9 nsec/iter (5) 76.5 cycles/iter; 383 instructions/iter; 13.9 nsec/iter (10) 63.7 cycles/iter; 318 instructions/iter; 11.6 nsec/iter (20) 71.6 cycles/iter; 344 instructions/iter; 13.0 nsec/iter (50) 77.5 cycles/iter; 419 instructions/iter; 14.1 nsec/iter (100) 143.4 cycles/iter; 893 instructions/iter; 26.1 nsec/iter (500) 270.8 cycles/iter; 1516 instructions/iter; 48.2 nsec/iter (1'000) Task-number: QTBUG-106201 Change-Id: I0745c33f0f61f1d844a60960cc55f565320d5945 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
70835a9335
commit
3c38efbfe4
@ -1342,14 +1342,7 @@ QByteArray &QByteArray::operator=(const char *str)
|
|||||||
} else if (!*str) {
|
} else if (!*str) {
|
||||||
d = DataPointer::fromRawData(&_empty, 0);
|
d = DataPointer::fromRawData(&_empty, 0);
|
||||||
} else {
|
} else {
|
||||||
const qsizetype len = qsizetype(strlen(str));
|
assign(str);
|
||||||
const auto capacityAtEnd = d->allocatedCapacity() - d.freeSpaceAtBegin();
|
|
||||||
if (d->needsDetach() || len > capacityAtEnd
|
|
||||||
|| (len < size() && len < (capacityAtEnd >> 1)))
|
|
||||||
// ### inefficient! reallocData() does copy the old data and we then overwrite it in the next line
|
|
||||||
reallocData(len, QArrayData::KeepSize);
|
|
||||||
memcpy(d.data(), str, len + 1); // include null terminator
|
|
||||||
d.size = len;
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,9 @@ private slots:
|
|||||||
|
|
||||||
void toPercentEncoding_data();
|
void toPercentEncoding_data();
|
||||||
void toPercentEncoding();
|
void toPercentEncoding();
|
||||||
|
|
||||||
|
void operator_assign_char();
|
||||||
|
void operator_assign_char_data();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_QByteArray::initTestCase()
|
void tst_QByteArray::initTestCase()
|
||||||
@ -353,6 +356,38 @@ void tst_QByteArray::toPercentEncoding()
|
|||||||
QTEST(encoded, "expected");
|
QTEST(encoded, "expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QByteArray::operator_assign_char()
|
||||||
|
{
|
||||||
|
QFETCH(QByteArray, data);
|
||||||
|
QString str(data.size(), Qt::Uninitialized);
|
||||||
|
|
||||||
|
const char *tdata = data.constData();
|
||||||
|
QBENCHMARK {
|
||||||
|
str.operator=(tdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QByteArray::operator_assign_char_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QByteArray>("data");
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
data.fill('a', 5);
|
||||||
|
QTest::newRow("length: 5") << data;
|
||||||
|
data.fill('b', 10);
|
||||||
|
QTest::newRow("length: 10") << data;
|
||||||
|
data.fill('c', 20);
|
||||||
|
QTest::newRow("length: 20") << data;
|
||||||
|
data.fill('d', 50);
|
||||||
|
QTest::newRow("length: 50") << data;
|
||||||
|
data.fill('e', 100);
|
||||||
|
QTest::newRow("length: 100") << data;
|
||||||
|
data.fill('f', 500);
|
||||||
|
QTest::newRow("length: 500") << data;
|
||||||
|
data.fill('g', 1'000);
|
||||||
|
QTest::newRow("length: 1'000") << data;
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QByteArray)
|
QTEST_MAIN(tst_QByteArray)
|
||||||
|
|
||||||
#include "tst_bench_qbytearray.moc"
|
#include "tst_bench_qbytearray.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user