diff options
author | Andrzej J.R. Hunt <andrzej@ahunt.org> | 2013-09-17 15:34:36 +0100 |
---|---|---|
committer | Andrzej J.R. Hunt <andrzej@ahunt.org> | 2013-09-27 18:09:18 +0100 |
commit | 7c87a5383ae03df0f9ad0e39cfbd6f83645a659a (patch) | |
tree | 32b502dbc3e9f36e120a8f4baf59d72585d1fe5a /dbaccess/qa | |
parent | 2fe4dd1e8b5dbcab7e313ad007ea35bf7ff01724 (diff) |
Implement firebird/hsqldb performance comparison test.
Change-Id: Iaf28b0fcb04ee713ccae6a593e56653eac6e2eba
Diffstat (limited to 'dbaccess/qa')
-rw-r--r-- | dbaccess/qa/unit/embeddeddb_performancetest.cxx | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/dbaccess/qa/unit/embeddeddb_performancetest.cxx b/dbaccess/qa/unit/embeddeddb_performancetest.cxx new file mode 100644 index 000000000000..7d511029a59b --- /dev/null +++ b/dbaccess/qa/unit/embeddeddb_performancetest.cxx @@ -0,0 +1,274 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "dbtest_base.cxx" + +#include <boost/scoped_ptr.hpp> +#include <osl/file.hxx> +#include <osl/process.h> +#include <osl/time.h> +#include <rtl/ustrbuf.hxx> +#include <tools/stream.hxx> + +#include <com/sun/star/sdb/XOfficeDatabaseDocument.hpp> +#include <com/sun/star/sdbc/XColumnLocate.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdbc/XParameters.hpp> +#include <com/sun/star/sdbc/XPreparedStatement.hpp> +#include <com/sun/star/sdbc/XResultSet.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbc/XStatement.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::uno; + +void normaliseTimeValue(TimeValue* pVal) +{ + pVal->Seconds += pVal->Nanosec / 1000000000; + pVal->Nanosec %= 1000000000; +} + +void getTimeDifference(const TimeValue* pTimeStart, + const TimeValue* pTimeEnd, + TimeValue* pTimeDifference) +{ + // We add 1 second to the nanoseconds to ensure that we get a positive number + // We have to normalise anyway so this doesn't cause any harm. + // (Seconds/Nanosec are both unsigned) + pTimeDifference->Seconds = pTimeEnd->Seconds - pTimeStart->Seconds - 1; + pTimeDifference->Nanosec = 1000000000 + pTimeEnd->Nanosec - pTimeStart->Nanosec; + normaliseTimeValue(pTimeDifference); +} + +OUString getPrintableTimeValue(const TimeValue* pTimeValue) +{ + return OUString::number( + (sal_uInt64(pTimeValue->Seconds) * SAL_CONST_UINT64(1000000000) + + sal_uInt64(pTimeValue->Nanosec))/ 1000000 + ); +} + +/* + * The reccomended way to run this test is: + * 'SAL_LOG="" DBA_PERFTEST=YES make CppunitTest_dbaccess_embeddeddb_performancetest' + * This blocks the unnecessary exception output and show only the performance data. + * + * You also need to create the file dbacess/qa/unit/data/wordlist, one easy way + * of generating a list is using 'aspell dump master > dbacess/qa/unit/data/wordlist' + * + * Note that wordlist cannot have more than 220580 lines, this is due to a hard + * limit in our hsqldb version. + * + * Also note that this unit test "fails" when doing performance testing, this is + * since by default unit test output is hidden, and thus there is no way of + * reading the results. + */ +class EmbeddedDBPerformanceTest + : public DBTestBase +{ +private: + const static OUString our_sEnableTestEnvVar; + + // We store the results and print them at the end due to the amount of warning + // noise present which otherwise obscures the results. + OUStringBuffer m_aOutputBuffer; + + void printTimes(const TimeValue* pTime1, const TimeValue* pTime2, const TimeValue* pTime3); + + void doPerformanceTestOnODB(const OUString& rFileName, const OUString& rDBName); + + void testFirebird(); + void testHSQLDB(); + +public: + void testPerformance(); + + CPPUNIT_TEST_SUITE(EmbeddedDBPerformanceTest); + CPPUNIT_TEST(testPerformance); + CPPUNIT_TEST_SUITE_END(); +}; + +void EmbeddedDBPerformanceTest::printTimes( + const TimeValue* pTime1, + const TimeValue* pTime2, + const TimeValue* pTime3) +{ + m_aOutputBuffer.append( + getPrintableTimeValue(pTime1) + "\t" + + getPrintableTimeValue(pTime2) + "\t" + + getPrintableTimeValue(pTime3) + "\t" + "\n" + ); +} + +const OUString EmbeddedDBPerformanceTest::our_sEnableTestEnvVar("DBA_PERFTEST"); + +// TODO: we probably should create a document from scratch instead? + +void EmbeddedDBPerformanceTest::testPerformance() +{ + OUString sEnabled; + osl_getEnvironment(our_sEnableTestEnvVar.pData, &sEnabled.pData); + + if (sEnabled.isEmpty()) + return; + + m_aOutputBuffer.append("---------------------\n"); + testFirebird(); + m_aOutputBuffer.append("---------------------\n"); + testHSQLDB(); + m_aOutputBuffer.append("---------------------\n"); + + fprintf(stdout, "Performance Test Results:\n"); + fprintf(stdout, "%s", + OUStringToOString(m_aOutputBuffer.makeStringAndClear(), + RTL_TEXTENCODING_UTF8) + .getStr() + ); + + // We want the results printed, but unit test output is only printed on failure + // Hence we deliberately fail the test. + CPPUNIT_ASSERT(false); +} + +void EmbeddedDBPerformanceTest::testFirebird() +{ + doPerformanceTestOnODB("firebird_empty.odb", "Firebird"); + +} + +void EmbeddedDBPerformanceTest::testHSQLDB() +{ + doPerformanceTestOnODB("hsqldb_empty.odb", "HSQLDB"); +} + +/** + * Use an existing .odb to do performance tests on. The database cannot have + * a table of the name PFTESTTABLE. + */ +void EmbeddedDBPerformanceTest::doPerformanceTestOnODB( + const OUString& rFileName, + const OUString& rDBName) +{ + uno::Reference< XOfficeDatabaseDocument > xDocument = + getDocumentForFileName(rFileName); + + uno::Reference< XConnection > xConnection = + getConnectionForDocument(xDocument); + + // Create Table + { + uno::Reference< XStatement > xStatement = xConnection->createStatement(); + CPPUNIT_ASSERT(xStatement.is()); + + // Although not strictly necessary we use quoted identifiers to reflect + // the fact that Base always uses quoted identifiers. + xStatement->execute( + "CREATE TABLE \"PFTESTTABLE\" ( \"ID\" INTEGER NOT NULL PRIMARY KEY " + ", \"STRINGCOLUMNA\" VARCHAR (50) " +// ", \"STRINGCOLUMNB\" VARCHAR (50) " +// ", \"STRINGCOLUMNC\" VARCHAR (50) " +// ", \"STRINGCOLUMND\" VARCHAR (50) " + ")"); + xConnection->commit(); + } + + // Writing test + { + uno::Reference< XPreparedStatement > xPreparedStatement = + xConnection->prepareStatement( + "INSERT INTO \"PFTESTTABLE\" ( \"ID\", " + "\"STRINGCOLUMNA\" " +// ", \"STRINGCOLUMNB\" " +// ", \"STRINGCOLUMNC\" " +// ", \"STRINGCOLUMND\" " + ") VALUES ( ?, ?" +// ", ?, ?, ? " + ")"); + + uno::Reference< XParameters > xParameters(xPreparedStatement, UNO_QUERY_THROW); + + ::boost::scoped_ptr< SvFileStream > pFile(new SvFileStream( + getSrcRootURL() + our_sFilePath + "wordlist", + STREAM_READ)); + + if (!pFile) + { + fprintf(stderr, "Please ensure the wordlist is present\n"); + CPPUNIT_ASSERT(false); + } + + OUString aWord; + sal_Int32 aID = 0; + + TimeValue aStart, aMiddle, aEnd; + osl_getSystemTime(&aStart); + + while (pFile->ReadByteStringLine(aWord, RTL_TEXTENCODING_UTF8)) + { + xParameters->setInt(1, aID++); + xParameters->setString(2, aWord); +// xParameters->setString(3, aWord); +// xParameters->setString(4, aWord); +// xParameters->setString(5, aWord); + xPreparedStatement->execute(); + } + osl_getSystemTime(&aMiddle); + xConnection->commit(); + osl_getSystemTime(&aEnd); + + + TimeValue aTimeInsert, aTimeCommit, aTimeTotal; + getTimeDifference(&aStart, &aMiddle, &aTimeInsert); + getTimeDifference(&aMiddle, &aEnd, &aTimeCommit); + getTimeDifference(&aStart, &aEnd, &aTimeTotal); + m_aOutputBuffer.append("Write to: " + rDBName + "\n"); + printTimes(&aTimeInsert, &aTimeCommit, &aTimeTotal); + + pFile->Close(); + } + + // Read test + { + uno::Reference< XStatement > xStatement = xConnection->createStatement(); + + TimeValue aStart, aMiddle, aEnd; + osl_getSystemTime(&aStart); + + uno::Reference< XResultSet > xResults = xStatement->executeQuery("SELECT * FROM PFTESTTABLE"); + + osl_getSystemTime(&aMiddle); + + uno::Reference< XRow > xRow(xResults, UNO_QUERY_THROW); + + while (xResults->next()) + { + xRow->getString(2); +// xRow->getString(3); +// xRow->getString(4); +// xRow->getString(5); + } + osl_getSystemTime(&aEnd); + + TimeValue aTimeSelect, aTimeIterate, aTimeTotal; + getTimeDifference(&aStart, &aMiddle, &aTimeSelect); + getTimeDifference(&aMiddle, &aEnd, &aTimeIterate); + getTimeDifference(&aStart, &aEnd, &aTimeTotal); + m_aOutputBuffer.append("Read from: " + rDBName + "\n"); + printTimes(&aTimeSelect, &aTimeIterate, &aTimeTotal); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(EmbeddedDBPerformanceTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |