/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include "qrawvector.h" #include /* Code generated by g++ 4.3.3. The lines marked with '!' are the ones that get executed inside the loop. Using the external 's' causes some load making the loop resembling a 'simple inner loop' in 'real' applications. qvector_mutable_read_access: .L166: ! movl -16(%ebp), %edx ! movl (%edx), %eax ! subl $1, %eax ! je .L165 movl 4(%edx), %eax movl %eax, 8(%esp) movl 8(%edx), %eax movl %esi, (%esp) movl %eax, 4(%esp) call _ZN4myns7QVectorIdE7reallocEii .L165: ! movl -16(%ebp), %eax ! fldl s ! faddl 16(%eax,%ebx,8) ! addl $1, %ebx ! cmpl $10000, %ebx ! fstpl s ! jne .L166 qvector_const_read_access: movl -16(%ebp), %edx xorl %eax, %eax .L183: ! fldl s ! faddl 16(%edx,%eax,8) ! addl $1, %eax ! cmpl $10000, %eax ! fstpl s ! jne .L183 stdvector_const_read_access and stdvector_mutable_read_access and qrawvector_const_read_access and qrawvector_mutable_read_access: xorl %eax, %eax .L64: ! fldl s ! faddl (%ebx,%eax,8) ! addl $1, %eax ! cmpl $10000, %eax ! fstpl s ! jne .L64 Behaviour varies with small modifications, but total is more or less stable: qrawvector_mutable_read_access, using size() instead of N: .L145: ! faddl (%edx,%eax,8) ! addl $1, %eax ! cmpl %ecx, %eax ! fstl s ! jne .L145 ! fstp %st(0) qrawvector_mutable_read_access, counting backward: .L145: ! faddl (%edx,%eax,8) ! subl $1, %eax ! cmpl $-1, %eax ! fstl s ! jne .L145 qrawvector_mutable_read_access, counting backward, using size(): .L146: ! faddl (%edx) ! addl $1, %eax ! subl $8, %edx ! cmpl %ecx, %eax ! fstl s ! jne .L146 */ /* //////////////////////////////////////////////////////////////////// time ./tst_vector qvector_const_read_access real 0m12.912s user 0m12.401s sys 0m0.016s time ./tst_vector qvector_mutable_read_access real 0m38.566s user 0m36.754s sys 0m0.008s time ./tst_vector stdvector_mutable_read_access real 0m12.736s user 0m12.665s sys 0m0.004s //////////////////////////////////////////////////////////////////// time ./tst_vector qvector_fill_and_return real 0m28.778s user 0m28.522s sys 0m0.012s time ./tst_vector stdvector_fill_and_return real 0m26.675s user 0m26.558s sys 0m0.012s time ./tst_vector qrawvector_fill_and_return real 0m23.370s user 0m23.269s sys 0m0.008s */ #define TEST_RETURN 1 // For some reason, both 'plain' and '-callgrind' create strange results // (like varying instruction count for the same assembly code) // So replace it by a plain loop and measure wall clock time. //#undef QBENCHMARK //#define QBENCHMARK for (int j = 0; j != 10000; ++j) class tst_QVector: public QObject { Q_OBJECT private slots: void calibration(); // Pure Qt solution void qvector_separator() { qWarning() << "QVector results: "; } void qvector_const_read_access(); void qvector_mutable_read_access(); #ifdef TEST_RETURN void qvector_fill_and_return(); #endif // Purre Standard solution void stdvector() { qWarning() << "std::vector results: "; } void stdvector_const_read_access(); void stdvector_mutable_read_access(); #ifdef TEST_RETURN void stdvector_fill_and_return(); #endif // Build using std, pass as QVector void mixedvector() { qWarning() << "mixed results: "; } #ifdef TEST_RETURN void mixedvector_fill_and_return(); #endif // Alternative implementation void qrawvector_separator() { qWarning() << "QRawVector results: "; } void qrawvector_const_read_access(); void qrawvector_mutable_read_access(); #ifdef TEST_RETURN void qrawvector_fill_and_return(); #endif }; const int N = 1000000; extern double s; void tst_QVector::calibration() { QVector v(N); for (int i = 0; i != N; ++i) v[i] = i; QBENCHMARK { for (int i = 0; i != N; ++i) s += i; } } ///////////////////// QVector ///////////////////// void tst_QVector::qvector_const_read_access() { QVector v(N); for (int i = 0; i != N; ++i) v[i] = i; const QVector &vc = v; QBENCHMARK { for (int i = 0; i != N; ++i) s += vc[i]; } } void tst_QVector::qvector_mutable_read_access() { QVector v(N); for (int i = 0; i != N; ++i) v[i] = i; QBENCHMARK { for (int i = 0; i != N; ++i) s += v[i]; } } #ifdef TEST_RETURN extern QVector qvector_fill_and_return_helper(); void tst_QVector::qvector_fill_and_return() { QBENCHMARK { QVector v = qvector_fill_and_return_helper(); s += v[1]; } } #endif ///////////////////// QRawVector ///////////////////// void tst_QVector::qrawvector_const_read_access() { QRawVector v(N); for (int i = 0; i != N; ++i) v[i] = i; const QRawVector &vc = v; QBENCHMARK { for (int i = vc.size(); --i >= 0;) s += vc[i]; } } void tst_QVector::qrawvector_mutable_read_access() { QRawVector v(N); for (int i = 0; i != N; ++i) v[i] = i; QBENCHMARK { for (int i = 0; i != N; ++i) s += v[i]; } } #ifdef TEST_RETURN extern QVector qrawvector_fill_and_return_helper(); void tst_QVector::qrawvector_fill_and_return() { QBENCHMARK { QVector v = qrawvector_fill_and_return_helper(); s += v[1]; } } #endif ///////////////////// std::vector ///////////////////// void tst_QVector::stdvector_const_read_access() { std::vector v(N); for (int i = 0; i != N; ++i) v[i] = i; const std::vector &vc = v; QBENCHMARK { for (int i = 0; i != N; ++i) s += vc[i]; } } void tst_QVector::stdvector_mutable_read_access() { std::vector v(N); for (int i = 0; i != N; ++i) v[i] = i; QBENCHMARK { for (int i = 0; i != N; ++i) s += v[i]; } } #ifdef TEST_RETURN extern std::vector stdvector_fill_and_return_helper(); void tst_QVector::stdvector_fill_and_return() { QBENCHMARK { std::vector v = stdvector_fill_and_return_helper(); s += v[1]; } } #endif ///////////////////// mixed vector ///////////////////// #ifdef TEST_RETURN extern QVector mixedvector_fill_and_return_helper(); void tst_QVector::mixedvector_fill_and_return() { QBENCHMARK { std::vector v = stdvector_fill_and_return_helper(); s += v[1]; } } #endif QTEST_MAIN(tst_QVector) #include "main.moc"