diff options
author | Alex Trotsenko <alex1973tr@gmail.com> | 2020-08-11 19:30:15 +0300 |
---|---|---|
committer | Alex Trotsenko <alex1973tr@gmail.com> | 2020-08-20 18:24:15 +0300 |
commit | a41c61fb2d2f973fd1cd5e95ee5be1ac1a4f8433 (patch) | |
tree | 857130e663aa61ebbf09d7da9a1670aa81a9e69b /src/corelib/io | |
parent | 729d102b1c5273087c54d1584c80f1a1e6eef86c (diff) |
QIODevice: implement a "zero-copy" strategy for buffered writes
It works as follows:
- user calls write(const QByteArray &);
- this function keeps a pointer to the chunk and calls a regular
write(data, len);
- write(data, len) calls a virtual writeData();
- subclass calls a new QIODevicePrivate::write();
- QIODevicePrivate::write() makes a shallow copy of
the byte array.
Proposed solution is fully compatible with existing subclasses.
By replacing a call to d->writeBuffer.append() with d->write(),
subclasses can improve their performance.
Bump the TypeInformationVersion field in qtHookData, to notify the
Qt Creator developers that the offset of QFilePrivate::fileName was
changed and dumpers should be adapted.
Change-Id: I24713386cc74a9f37e5223c617e4b1ba97f968dc
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qiodevice.cpp | 32 | ||||
-rw-r--r-- | src/corelib/io/qiodevice_p.h | 4 | ||||
-rw-r--r-- | src/corelib/io/qprocess.cpp | 2 |
3 files changed, 34 insertions, 4 deletions
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 3d64e8820f..b920fbb17b 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -158,13 +158,14 @@ static void checkWarnMessage(const QIODevice *device, const char *function, cons QIODevicePrivate::QIODevicePrivate() : openMode(QIODevice::NotOpen), pos(0), devicePos(0), + transactionPos(0), readChannelCount(0), writeChannelCount(0), currentReadChannel(0), currentWriteChannel(0), readBufferChunkSize(QIODEVICE_BUFFERSIZE), writeBufferChunkSize(0), - transactionPos(0), + currentWriteChunk(nullptr), transactionStarted(false) , baseReadLineDataCalled(false) , accessMode(Unset) @@ -1750,7 +1751,34 @@ qint64 QIODevice::write(const char *data) qint64 QIODevice::write(const QByteArray &data) { - return write(data.constData(), data.size()); + Q_D(QIODevice); + + // Keep the chunk pointer for further processing in + // QIODevicePrivate::write(). To reduce fragmentation, + // the chunk size must be sufficiently large. + if (data.size() >= QRINGBUFFER_CHUNKSIZE) + d->currentWriteChunk = &data; + + const qint64 ret = write(data.constData(), data.size()); + + d->currentWriteChunk = nullptr; + return ret; +} + +/*! + \internal +*/ +void QIODevicePrivate::write(const char *data, qint64 size) +{ + if (currentWriteChunk != nullptr + && currentWriteChunk->constData() == data + && currentWriteChunk->size() == size) { + // We are called from write(const QByteArray &) overload. + // So, we can make a shallow copy of chunk. + writeBuffer.append(*currentWriteChunk); + } else { + writeBuffer.append(data, size); + } } /*! diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h index d8e12d7259..a485ec43b3 100644 --- a/src/corelib/io/qiodevice_p.h +++ b/src/corelib/io/qiodevice_p.h @@ -124,13 +124,14 @@ public: QRingBufferRef writeBuffer; qint64 pos; qint64 devicePos; + qint64 transactionPos; int readChannelCount; int writeChannelCount; int currentReadChannel; int currentWriteChannel; int readBufferChunkSize; int writeBufferChunkSize; - qint64 transactionPos; + const QByteArray *currentWriteChunk; bool transactionStarted; bool baseReadLineDataCalled; @@ -175,6 +176,7 @@ public: virtual qint64 peek(char *data, qint64 maxSize); virtual QByteArray peek(qint64 maxSize); qint64 skipByReading(qint64 maxSize); + void write(const char *data, qint64 size); #ifdef QT_NO_QOBJECT QIODevice *q_ptr; diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index b56ead8584..8e8664fda4 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1899,7 +1899,7 @@ qint64 QProcess::writeData(const char *data, qint64 len) } #endif - d->writeBuffer.append(data, len); + d->write(data, len); #ifdef Q_OS_WIN if (!d->stdinWriteTrigger->isActive()) d->stdinWriteTrigger->start(); |