summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Trotsenko <alex1973tr@gmail.com>2016-09-17 16:43:02 +0300
committerAlex Trotsenko <alex1973tr@gmail.com>2017-02-09 18:46:24 +0000
commit6e8fcab7e07717526c8ea6eac8785bf27fa090c3 (patch)
treea6ea9825b55b3b406515e88462c54b448ff672a6 /src
parent60563855e589cb51b4966ca51a4d390a2f1609a4 (diff)
Improve QIODevice::peek() performance on buffered devices
Since 5.7, QIODevice::peek() implementation is based on transaction mechanism. While technically it's correct, seeking backward on a buffered random-access device clears the internal buffer that affects the performance of reading. To solve the problem, this patch implements peek mode directly inside the reading procedure. Task-number: QTBUG-56032 Change-Id: Ic5269f76e44c491a0309e13aba87fa7cf7b9259f Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qiodevice.cpp83
-rw-r--r--src/corelib/io/qiodevice_p.h2
2 files changed, 40 insertions, 45 deletions
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 8cef993cf4..41a4d7a1ba 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -1047,26 +1047,29 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
/*!
\internal
*/
-qint64 QIODevicePrivate::read(char *data, qint64 maxSize)
+qint64 QIODevicePrivate::read(char *data, qint64 maxSize, bool peeking)
{
Q_Q(QIODevice);
const bool buffered = (openMode & QIODevice::Unbuffered) == 0;
const bool sequential = isSequential();
- const bool keepDataInBuffer = sequential && transactionStarted;
+ const bool keepDataInBuffer = sequential
+ ? peeking || transactionStarted
+ : peeking && buffered;
+ const qint64 savedPos = pos;
qint64 readSoFar = 0;
bool madeBufferReadsOnly = true;
bool deviceAtEof = false;
char *readPtr = data;
+ qint64 bufferPos = (sequential && transactionStarted) ? transactionPos : Q_INT64_C(0);
forever {
// Try reading from the buffer.
qint64 bufferReadChunkSize = keepDataInBuffer
- ? buffer.peek(data, maxSize, transactionPos)
+ ? buffer.peek(data, maxSize, bufferPos)
: buffer.read(data, maxSize);
if (bufferReadChunkSize > 0) {
- if (keepDataInBuffer)
- transactionPos += bufferReadChunkSize;
- else if (!sequential)
+ bufferPos += bufferReadChunkSize;
+ if (!sequential)
pos += bufferReadChunkSize;
#if defined QIODEVICE_DEBUG
printf("%p \treading %lld bytes from buffer into position %lld\n", q,
@@ -1160,6 +1163,16 @@ qint64 QIODevicePrivate::read(char *data, qint64 maxSize)
break;
}
+ // Restore positions after reading
+ if (keepDataInBuffer) {
+ if (peeking)
+ pos = savedPos; // does nothing on sequential devices
+ else
+ transactionPos = bufferPos;
+ } else if (peeking) {
+ seekBuffer(savedPos); // unbuffered random-access device
+ }
+
if (madeBufferReadsOnly && isBufferEmpty())
q->readData(data, 0);
@@ -1773,27 +1786,7 @@ bool QIODevicePrivate::putCharHelper(char c)
*/
qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
{
- Q_Q(QIODevice);
-
- if (transactionStarted) {
- const qint64 savedTransactionPos = transactionPos;
- const qint64 savedPos = pos;
-
- qint64 readBytes = q->read(data, maxSize);
-
- // Restore initial position
- if (isSequential())
- transactionPos = savedTransactionPos;
- else
- seekBuffer(savedPos);
- return readBytes;
- }
-
- q->startTransaction();
- qint64 readBytes = q->read(data, maxSize);
- q->rollbackTransaction();
-
- return readBytes;
+ return read(data, maxSize, true);
}
/*!
@@ -1801,26 +1794,17 @@ qint64 QIODevicePrivate::peek(char *data, qint64 maxSize)
*/
QByteArray QIODevicePrivate::peek(qint64 maxSize)
{
- Q_Q(QIODevice);
+ QByteArray result(maxSize, Qt::Uninitialized);
- if (transactionStarted) {
- const qint64 savedTransactionPos = transactionPos;
- const qint64 savedPos = pos;
+ const qint64 readBytes = read(result.data(), maxSize, true);
- QByteArray result = q->read(maxSize);
-
- // Restore initial position
- if (isSequential())
- transactionPos = savedTransactionPos;
+ if (readBytes < maxSize) {
+ if (readBytes <= 0)
+ result.clear();
else
- seekBuffer(savedPos);
- return result;
+ result.resize(readBytes);
}
- q->startTransaction();
- QByteArray result = q->read(maxSize);
- q->rollbackTransaction();
-
return result;
}
@@ -1858,7 +1842,12 @@ bool QIODevice::getChar(char *c)
*/
qint64 QIODevice::peek(char *data, qint64 maxSize)
{
- return d_func()->peek(data, maxSize);
+ Q_D(QIODevice);
+
+ CHECK_MAXLEN(peek, qint64(-1));
+ CHECK_READABLE(peek, qint64(-1));
+
+ return d->peek(data, maxSize);
}
/*!
@@ -1880,7 +1869,13 @@ qint64 QIODevice::peek(char *data, qint64 maxSize)
*/
QByteArray QIODevice::peek(qint64 maxSize)
{
- return d_func()->peek(maxSize);
+ Q_D(QIODevice);
+
+ CHECK_MAXLEN(peek, QByteArray());
+ CHECK_MAXBYTEARRAYSIZE(peek);
+ CHECK_READABLE(peek, QByteArray());
+
+ return d->peek(maxSize);
}
/*!
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index 0e424b6831..71a326dd53 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -171,7 +171,7 @@ public:
void setReadChannelCount(int count);
void setWriteChannelCount(int count);
- qint64 read(char *data, qint64 maxSize);
+ qint64 read(char *data, qint64 maxSize, bool peeking = false);
virtual qint64 peek(char *data, qint64 maxSize);
virtual QByteArray peek(qint64 maxSize);