summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShane Kearns <ext-shane.2.kearns@nokia.com>2012-03-08 11:45:05 +0000
committerPasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>2012-03-19 11:40:24 +0100
commitea2bf09534884d52b2c5b40bc214b80cfb5526e5 (patch)
tree2dc9aa27864e444579d5ef2cc0dbc657602418b5
parent7be97ebddb27d570c6bcbe8ad881d890ea6a5d2d (diff)
downloadqt4-tools-ea2bf09534884d52b2c5b40bc214b80cfb5526e5.tar.gz
Optimise QFile::seek that doesn't move the file pointer
If the seek position matches the current file position, then avoid doing an implicit flush that could be expensive. Change-Id: I019858ffb36fe832b9aee8da0a7803cafc8f7f75 Reviewed-by: Jaakko Helanti <ext-jaakko.helanti@nokia.com> Reviewed-by: João Abecasis <joao.abecasis@nokia.com> (cherry picked from commit a3a2ff59284840f1980197e3f6d06d99fcc0f512) Reviewed-by: Pasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>
-rw-r--r--src/corelib/io/qfile.cpp3
-rw-r--r--tests/auto/qfile/tst_qfile.cpp55
-rw-r--r--tests/benchmarks/corelib/io/qfile/main.cpp104
3 files changed, 162 insertions, 0 deletions
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 09d0c589f9..f993580e87 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -1692,6 +1692,9 @@ bool QFile::seek(qint64 off)
return false;
}
+ if (off == d->pos && off == d->devicePos)
+ return true; //avoid expensive flush for NOP seek to current position
+
if (!d->ensureFlushed())
return false;
diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp
index b7a33731ee..5c8bc2b17d 100644
--- a/tests/auto/qfile/tst_qfile.cpp
+++ b/tests/auto/qfile/tst_qfile.cpp
@@ -128,6 +128,7 @@ private slots:
void seek();
void setSize();
void setSizeSeek();
+ void seekToSamePosition();
void atEnd();
void readLine();
void readLine2();
@@ -458,6 +459,7 @@ void tst_QFile::cleanupTestCase()
QFile::remove("readAllBuffer.txt");
QFile::remove("qt_file.tmp");
QFile::remove("File.txt");
+ QFile::remove("seekToSamePosition.txt");
}
//------------------------------------------
@@ -756,6 +758,59 @@ void tst_QFile::setSizeSeek()
QCOMPARE(f.pos(), qint64(2));
}
+void tst_QFile::seekToSamePosition()
+{
+ QFile in("testfile.txt");
+ QFile out("seekToSamePosition.txt");
+ QVERIFY(in.open(QFile::ReadOnly));
+ QVERIFY(out.open(QFile::WriteOnly));
+ QByteArray plusses;
+ plusses.fill('+', 58);
+
+ qint64 cursor = 0;
+ QVERIFY(in.seek(cursor));
+ QVERIFY(out.seek(cursor));
+
+ QVERIFY(out.write(plusses));
+
+ cursor += 58;
+ QVERIFY(in.seek(cursor));
+ QVERIFY(out.seek(cursor));
+
+ QByteArray copy = in.read(60);
+ QVERIFY(out.write(copy));
+
+ cursor += 60;
+ QVERIFY(in.seek(cursor));
+ QVERIFY(out.seek(cursor));
+
+ QVERIFY(out.write(plusses));
+
+ cursor += 58;
+ QVERIFY(in.seek(cursor));
+ QVERIFY(out.seek(cursor));
+
+ copy = in.readAll();
+ QVERIFY(out.write(copy));
+
+ //compare
+ out.close();
+ QVERIFY(out.open(QFile::ReadOnly));
+ QVERIFY(in.seek(0));
+
+ QByteArray clean = in.readAll();
+ QByteArray dirty = out.readAll();
+ out.close();
+
+ QVERIFY(clean.size() == dirty.size());
+ for (int i=0;i<clean.size();i++) {
+ if (clean[i] == '-')
+ QVERIFY2(dirty[i] == '+', qPrintable(QString("no + at pos %1").arg(i)));
+ else
+ QVERIFY2(dirty[i] == clean[i], qPrintable(QString("char at pos %1 mismatched, %2 vs %3").arg(i).arg(clean[i]).arg(dirty[i])));
+ }
+}
+
void tst_QFile::atEnd()
{
QFile f( SRCDIR "testfile.txt" );
diff --git a/tests/benchmarks/corelib/io/qfile/main.cpp b/tests/benchmarks/corelib/io/qfile/main.cpp
index e22637ae7b..e7d260945c 100644
--- a/tests/benchmarks/corelib/io/qfile/main.cpp
+++ b/tests/benchmarks/corelib/io/qfile/main.cpp
@@ -113,6 +113,13 @@ private slots:
void readBigFile_posix();
void readBigFile_Win32();
+ void writeFileSequential_data();
+ void writeFileSequential();
+ void writeFileBackwards_data();
+ void writeFileBackwards();
+ void writeFileSequentialWithSeeks_data();
+ void writeFileSequentialWithSeeks();
+
private:
void readBigFile_data(BenchmarkType type, QIODevice::OpenModeFlag t, QIODevice::OpenModeFlag b);
void readBigFile();
@@ -678,6 +685,103 @@ void tst_qfile::readSmallFiles()
delete[] buffer;
}
+void tst_qfile::writeFileSequential_data()
+{
+ QTest::addColumn<int>("blockSize");
+ QTest::addColumn<QString>("path");
+
+ QTest::newRow("internal 16b") << 16 << QDir::tempPath();
+ QTest::newRow("internal 512b") << 512 << QDir::tempPath();
+ QTest::newRow("internal 4k") << 4096 << QDir::tempPath();
+ QTest::newRow("internal 16k") << 16384 << QDir::tempPath();
+ QTest::newRow("internal 64k") << 65536 << QDir::tempPath();
+
+ //slow media (e.g. SD card)
+ QString externalPath;
+#ifdef Q_OS_SYMBIAN
+ externalPath = "E:/";
+#endif
+ if (!externalPath.isEmpty()) {
+ QTest::newRow("external 16b") << 16 << externalPath;
+ QTest::newRow("external 512b") << 512 << externalPath;
+ QTest::newRow("external 4k") << 4096 << externalPath;
+ QTest::newRow("external 16k") << 16384 << externalPath;
+ QTest::newRow("external 64k") << 65536 << externalPath;
+ }
+}
+
+void tst_qfile::writeFileSequential()
+{
+ const qint64 limit = 1024 * 1024;
+ QFETCH(int, blockSize);
+ QFETCH(QString, path);
+ QTemporaryFile f;
+ f.setFileTemplate(path);
+ QByteArray block;
+ block.fill('@', blockSize);
+ QBENCHMARK {
+ QVERIFY(f.open());
+ for (qint64 pos = 0; pos < limit; pos += blockSize) {
+ QVERIFY(f.write(block));
+ }
+ QVERIFY(f.flush());
+ QCOMPARE(f.size(), limit);
+ f.close();
+ }
+}
+
+void tst_qfile::writeFileBackwards_data()
+{
+ writeFileSequential_data();
+}
+
+void tst_qfile::writeFileBackwards()
+{
+ const qint64 limit = 1024 * 1024;
+ QFETCH(int, blockSize);
+ QFETCH(QString, path);
+ QTemporaryFile f;
+ f.setFileTemplate(path);
+ QByteArray block;
+ block.fill('@', blockSize);
+ QBENCHMARK {
+ QVERIFY(f.open());
+ for (qint64 pos = limit - blockSize; pos >= 0; pos -= blockSize) {
+ QVERIFY(f.seek(pos));
+ QVERIFY(f.write(block));
+ }
+ QVERIFY(f.flush());
+ QCOMPARE(f.size(), limit);
+ f.close();
+ }
+}
+
+void tst_qfile::writeFileSequentialWithSeeks_data()
+{
+ writeFileSequential_data();
+}
+
+void tst_qfile::writeFileSequentialWithSeeks()
+{
+ const qint64 limit = 1024 * 1024;
+ QFETCH(int, blockSize);
+ QFETCH(QString, path);
+ QTemporaryFile f;
+ f.setFileTemplate(path);
+ QByteArray block;
+ block.fill('@', blockSize);
+ QBENCHMARK {
+ QVERIFY(f.open());
+ for (qint64 pos = 0; pos < limit; pos += blockSize) {
+ QVERIFY(f.seek(pos));
+ QVERIFY(f.write(block));
+ }
+ QVERIFY(f.flush());
+ QCOMPARE(f.size(), limit);
+ f.close();
+ }
+}
+
QTEST_MAIN(tst_qfile)
#include "main.moc"