persistentstorage/dbms/tdbms/t_dbbench.cpp
changeset 55 44f437012c90
parent 0 08ec8eefde2f
--- a/persistentstorage/dbms/tdbms/t_dbbench.cpp	Mon Sep 27 11:59:56 2010 +0100
+++ b/persistentstorage/dbms/tdbms/t_dbbench.cpp	Tue Oct 19 16:26:13 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1998-2010 Nokia Corporation and/or its subsidiary(-ies).
 // All rights reserved.
 // This component and the accompanying materials are made available
 // under the terms of "Eclipse Public License v1.0"
@@ -20,157 +20,32 @@
 #include <e32svr.h>
 #include <hal.h>
 #include <d32dbmsconstants.h>
-
-// MSVC++ up to 5.0 has problems with expanding inline functions
-// This disables the mad warnings for the whole project
-#if defined(NDEBUG) && defined(__VC32__) && _MSC_VER<=1100
-#pragma warning(disable : 4710)			// function not expanded. MSVC 5.0 is stupid
-#endif
+#include "t_dbcmdlineutil.h"
 
-class TTimer
-	{
-public:
-	void Start();
-	TReal Stop() const;
-private:
-	TUint iTicks;
-	};
+TCmdLineParams TheCmdLineParams;
+TFileName TheDbFileName;
+RFile TheLogFile; 
+RTest TheTest(_L("t_dbbench"));
+RDbNamedDatabase TheDatabase;
+RDbView TheView;
+RFs TheFs;
 
-LOCAL_D RTest test(_L("t_dbbench"));
-LOCAL_D CTrapCleanup* TheTrapCleanup;
-LOCAL_D RDbNamedDatabase TheDatabase;
-LOCAL_D RDbView TheView;
-LOCAL_D RFs TheFs;
+TBuf<250> TheLogLine;
+TBuf8<250> TheLogLine8;
 
-const TInt KTestCleanupStack=0x20;
-//T_BENCH file shall not be deleted at the end of the test! It will be used by T_COMP test.
-const TPtrC KTestDatabase=_S("\\DBMS-TST\\T_BENCH.DB");
 const TPtrC KTableName=_S("Test");
 const TPtrC KColCluster=_S("Cluster");
 const TPtrC KColXcluster=_S("xCluster");
 const TPtrC KColRandom=_S("Random");
 const TPtrC KColXrandom=_S("xRandom");
-const TInt KRecords=2000;
-
-static TTimer TheTimer;
-
-void TTimer::Start()
-	{
-	iTicks=User::FastCounter();
-	}
-
-TReal TTimer::Stop() const
-	{
-	TUint ticks = User::FastCounter() - iTicks;
-	TInt freq = 0;
-	test(HAL::Get(HAL::EFastCounterFrequency, freq) == KErrNone);
-	const TInt KMicroSecIn1Sec = 1000000;
-	const TInt KMsIn1Sec = 1000;
-	double v = ((double)ticks * KMicroSecIn1Sec) / (double)freq; TInt v2 = (TInt)v;
-	return v2 / KMsIn1Sec;
-	}
-
-LOCAL_C void CloseDatabase()
-	{
-	TheDatabase.Close();
-	}
-
-/**
-Create the database: keep the code 050 compatible
-
-@SYMTestCaseID          SYSLIB-DBMS-CT-0577
-@SYMTestCaseDesc        Benchmark Tests. Creation of a local Database test
-@SYMTestPriority        Medium
-@SYMTestActions        	Attempt to test RDbNamedDatabase::CreateTable(),RDbNamedDatabase::CreateIndex(),
-						RDbNamedDatabase::Compact(),RDbView::Prepare() functions
-@SYMTestExpectedResults Test must not fail
-@SYMREQ                 REQ0000
-*/
-LOCAL_C void CreateDatabaseL()
-	{
-	test.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0577 "));
-	User::LeaveIfError(TheDatabase.Replace(TheFs,KTestDatabase));
-	CDbColSet& set=*CDbColSet::NewLC();
-	TDbCol col(KColCluster,EDbColInt32);
-	col.iAttributes=col.ENotNull;
-	set.AddL(col);
-	col.iName=KColXcluster;
-	set.AddL(col);
-	col.iName=KColRandom;
-	set.AddL(col);
-	col.iName=KColXrandom;
-	set.AddL(col);
-	TInt r=TheDatabase.CreateTable(KTableName,set);
-	test (r==KErrNone);
-	CleanupStack::PopAndDestroy();
-	TheTimer.Start();
-	r=TheView.Prepare(TheDatabase,_L("select * from test"),TheView.EInsertOnly);
-	TheDatabase.Begin();
-	test (r==KErrNone);
-	TInt jj=0;
-	for (TInt ii=0;ii<KRecords;++ii)
-		{
-		TheView.InsertL();
-		jj=(jj+23);
-		if (jj>=KRecords)
-			jj-=KRecords;
-		TheView.SetColL(1,ii);
-		TheView.SetColL(2,ii);
-		TheView.SetColL(3,jj);
-		TheView.SetColL(4,jj);
-		TheView.PutL();
-		}
-	r=TheDatabase.Commit();
-	test (r==KErrNone);
-	TheView.Close();
-	test.Printf(_L("Build table: %7.1f ms\n"),TheTimer.Stop());
-	TheTimer.Start();
-	CDbKey& key=*CDbKey::NewLC();
-	key.AddL(KColXcluster);
-	key.MakeUnique();
-	r=TheDatabase.CreateIndex(KColXcluster,KTableName,key);
-	test (r==KErrNone);
-	test.Printf(_L("Cluster index: %7.1f ms\n"),TheTimer.Stop());
-	TheTimer.Start();
-	key.Clear();
-	key.AddL(KColXrandom);
-	r=TheDatabase.CreateIndex(KColXrandom,KTableName,key);
-	test (r==KErrNone);
-	CleanupStack::PopAndDestroy();
-	test.Printf(_L("Random index: %7.1f ms\n"),TheTimer.Stop());
-	TheTimer.Start();
-	r = TheDatabase.Compact();
-	test.Printf(_L("Compact: %7.1f ms\n"),TheTimer.Stop());
-	test (r == KErrNone);
-	}
-
-LOCAL_C TReal Evaluate(const TDesC& aSql)
-	{
-	TInt m=1;
-	for (;;)
-		{
-		TheTimer.Start();
-		for (TInt ii=0;ii<m;++ii)
-			{
-			TInt r=TheView.Prepare(TheDatabase,aSql,KDbUnlimitedWindow,TheView.EReadOnly);
-			if (r<0)
-				return r;
-			r=TheView.EvaluateAll();
-			test (r==KErrNone);
-			TheView.Close();
-			}
-		TReal t=TheTimer.Stop();
-		if (t>=100.0)
-			return t/m;
-		m*=4;
-		}
-	}
+const TInt  KRecords=2000;
 
 struct TTest
 	{
 	const TText* iName;
 	const TText* iQuery;
 	};
+
 const TTest KQuery[]=
 	{
 	{_S("project"),_S("select cluster,xcluster,random,xrandom from test")},
@@ -185,6 +60,200 @@
 	{_S("all 4"),_S("select * from test where xcluster<500 and xrandom<200 order by xcluster")}
 	};
 
+///////////////////////////////////////////////////////////////////////////////////////
+
+void TestEnvDestroy()
+	{
+	TheView.Close();
+	TheDatabase.Close();
+	if(TheCmdLineParams.iLogFileName.Length() > 0)
+		{
+		(void)TheLogFile.Flush();
+		TheLogFile.Close();
+		}
+	//T_BENCH.DB cannot be deleted here, because it is used by T_DBCOMP test!
+	TheFs.Close();
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////
+//Test macros and functions
+void Check1(TInt aValue, TInt aLine)
+	{
+	if(!aValue)
+		{
+		TestEnvDestroy();
+		TheTest.Printf(_L("*** Line %d. Expression evaluated to false\r\n"), aLine);
+		TheTest(EFalse, aLine);
+		}
+	}
+void Check2(TInt aValue, TInt aExpected, TInt aLine)
+	{
+	if(aValue != aExpected)
+		{
+		TestEnvDestroy();
+		TheTest.Printf(_L("*** Line %d, Expected error: %d, got: %d\r\n"), aLine, aExpected, aValue);
+		TheTest(EFalse, aLine);
+		}
+	}
+#define TEST(arg) ::Check1((arg), __LINE__)
+#define TEST2(aValue, aExpected) ::Check2(aValue, aExpected, __LINE__)
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+TInt FastCounterFrequency()
+	{
+	static TInt freq = 0;
+	if(freq == 0)
+		{
+		TEST2(HAL::Get(HAL::EFastCounterFrequency, freq), KErrNone);
+		}
+	return freq;
+	}
+
+//Prints the test case title and execution time in microseconds
+void PrintResult(const TDesC& aTitle, TUint32 aStartTicks, TUint32 aEndTicks, TInt aIterations = 0)
+	{
+	TInt freq = FastCounterFrequency();
+	TInt64 diffTicks = (TInt64)aEndTicks - (TInt64)aStartTicks;
+	if(diffTicks < 0)
+		{
+		diffTicks = KMaxTUint32 + diffTicks + 1;
+		}
+	const TInt KMicroSecIn1Sec = 1000000;
+	TInt32 us = (diffTicks * KMicroSecIn1Sec) / freq;
+	if(aIterations > 0)
+		{
+		us /= aIterations;
+		}
+	TheTest.Printf(_L("%S: %d us\r\n"), &aTitle, us);
+	if(TheCmdLineParams.iLogFileName.Length() > 0)
+		{
+		TheLogLine.Format(_L("%S¬%d¬us\r\n"), &aTitle, us);
+		TheLogLine8.Copy(TheLogLine);
+		(void)TheLogFile.Write(TheLogLine8);
+		}
+	}
+
+//Calculates time in microseconds
+TInt CalcTime(TUint32 aStartTicks, TUint32 aEndTicks)
+	{
+	TInt freq = FastCounterFrequency();
+	TInt64 diffTicks = (TInt64)aEndTicks - (TInt64)aStartTicks;
+	if(diffTicks < 0)
+		{
+		diffTicks = KMaxTUint32 + diffTicks + 1;
+		}
+	const TInt KMicroSecIn1Sec = 1000000;
+	TInt32 us = (diffTicks * KMicroSecIn1Sec) / freq;
+	return us;
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Create the database: keep the code 050 compatible
+
+@SYMTestCaseID          SYSLIB-DBMS-CT-0577
+@SYMTestCaseDesc        Benchmark Tests. Creation of a local Database test
+@SYMTestPriority        Medium
+@SYMTestActions        	Attempt to test RDbNamedDatabase::CreateTable(),RDbNamedDatabase::CreateIndex(),
+						RDbNamedDatabase::Compact(),RDbView::Prepare() functions
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+void CreateDatabaseL()
+	{
+	TInt err = TheDatabase.Replace(TheFs, TheDbFileName);
+	TEST2(err, KErrNone);
+	
+	CDbColSet* set = CDbColSet::NewLC();
+	TDbCol col(KColCluster,EDbColInt32);
+	col.iAttributes=col.ENotNull;
+	set->AddL(col);
+	col.iName=KColXcluster;
+	set->AddL(col);
+	col.iName=KColRandom;
+	set->AddL(col);
+	col.iName=KColXrandom;
+	set->AddL(col);
+	
+	err = TheDatabase.CreateTable(KTableName, *set);
+	TEST2(err, KErrNone);
+	CleanupStack::PopAndDestroy(set);
+	
+	TUint32 ticksStart = User::FastCounter();
+	err = TheView.Prepare(TheDatabase,_L("select * from test"),TheView.EInsertOnly);
+	TEST2(err, KErrNone);
+	TheDatabase.Begin();
+	TInt jj=0;
+	for (TInt ii=0;ii<KRecords;++ii)
+		{
+		TheView.InsertL();
+		jj=(jj+23);
+		if (jj>=KRecords)
+			jj-=KRecords;
+		TheView.SetColL(1,ii);
+		TheView.SetColL(2,ii);
+		TheView.SetColL(3,jj);
+		TheView.SetColL(4,jj);
+		TheView.PutL();
+		}
+	err = TheDatabase.Commit();
+	TEST2(err, KErrNone);
+	TheView.Close();
+	TUint32 ticksEnd = User::FastCounter();
+	PrintResult(_L("Build table"), ticksStart, ticksEnd);
+	
+	ticksStart = User::FastCounter();
+	CDbKey* key = CDbKey::NewLC();
+	key->AddL(KColXcluster);
+	key->MakeUnique();
+	err = TheDatabase.CreateIndex(KColXcluster,KTableName,*key);
+	TEST2(err, KErrNone);
+	ticksEnd = User::FastCounter();
+	PrintResult(_L("Cluster index"), ticksStart, ticksEnd);
+	
+	ticksStart = User::FastCounter();
+	key->Clear();
+	key->AddL(KColXrandom);
+	err = TheDatabase.CreateIndex(KColXrandom,KTableName,*key);
+	TEST2(err, KErrNone);
+	CleanupStack::PopAndDestroy(key);
+	ticksEnd = User::FastCounter();
+	PrintResult(_L("Random index"), ticksStart, ticksEnd);
+	
+	ticksStart = User::FastCounter();
+	err = TheDatabase.Compact();
+	ticksEnd = User::FastCounter();
+	PrintResult(_L("Compact"), ticksStart, ticksEnd);
+	TEST2(err, KErrNone);
+	}
+
+void Evaluate(const TDesC& aTitle, const TDesC& aSql)
+	{
+	TInt m = 1;
+	for(;;)
+		{
+		TUint32 ticksStart = User::FastCounter();
+		for(TInt i=0; i<m; ++i)
+			{
+			TInt err = TheView.Prepare(TheDatabase,aSql,KDbUnlimitedWindow,TheView.EReadOnly);
+			TEST2(err, KErrNone);
+			err = TheView.EvaluateAll();
+			TEST2(err, KErrNone);
+			TheView.Close();
+			}
+		TUint32 ticksEnd = User::FastCounter();
+		TInt us = CalcTime(ticksStart, ticksEnd);
+		if(us > 100000)
+			{
+			PrintResult(aTitle, ticksStart, ticksEnd, m);
+			return;
+			}
+		m *= 4;
+		}
+	}
+
 /**
 @SYMTestCaseID          SYSLIB-DBMS-CT-0578
 @SYMTestCaseDesc        Benchmark Test.Querying a local Database Test
@@ -193,102 +262,68 @@
 @SYMTestExpectedResults Test must not fail
 @SYMREQ                 REQ0000
 */
-LOCAL_C void Queries()
+void Queries()
 	{
-	test.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0578 "));
-	for (TUint ii=0;ii<sizeof(KQuery)/sizeof(KQuery[0]);++ii)
+	for(TUint ii=0;ii<sizeof(KQuery)/sizeof(KQuery[0]);++ii)
 		{
-		test.Printf(_L("%15s: "),KQuery[ii].iName);
-		TReal t=Evaluate(TPtrC(KQuery[ii].iQuery));
-		if (t<0.0)
-			test.Printf(_L("-\n"));
-		else
-			test.Printf(_L("%7.1f ms\n"),t);
+		Evaluate(TPtrC(KQuery[ii].iName), TPtrC(KQuery[ii].iQuery));
 		}
 	}
 
-//
-// Benchmark tests
-//
-LOCAL_C void BenchTestL()
+void BenchTestL()
 	{
+	TheTest.Start(_L("@SYMTestCaseID:SYSLIB-DBMS-CT-0577 RDbNamedDatabase performance test"));
 	CreateDatabaseL();
+	
+	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0578 SQL queries performance test"));
 	Queries();
-	CloseDatabase();
+	
+	TheDatabase.Close();
 	}
 
-//
-// Prepare the test directory.
-//
-LOCAL_C void setupTestDirectory()
+void TestEnvInit()
     {
-	TInt r=TheFs.Connect();
-	test(r==KErrNone);
-//
-#if 0
-	TDriveList drives;
-	TheFs.DriveList(drives);
-	if (drives[EDriveK] == KDriveAbsent)
+	TInt err = TheFs.Connect();
+	TEST2(err, KErrNone);
+	
+	err = TheFs.MkDirAll(TheDbFileName);
+	TEST(err == KErrNone || err == KErrAlreadyExists);
+	
+	if(TheCmdLineParams.iLogFileName.Length() > 0)
 		{
-		TInt r = TheFs.AddFileSystem(_L("ELFFS"));
-		test (r == KErrNone);
-		r = TheFs.MountFileSystem(_L("Lffs"),EDriveK);
-		if (r == KErrCorrupt || r == KErrNotReady)
-			{
-			RFormat format;
-			TInt    count;
-			r = format.Open(TheFs, _L("K:\\"), EHighDensity, count);
-			test (r == KErrNone);
-			while (count)
-				format.Next(count);
-			format.Close();
-    		}
-		else
-			test (r == KErrNone);
+		err = TheLogFile.Replace(TheFs, TheCmdLineParams.iLogFileName, EFileRead | EFileWrite);
+		TEST2(err, KErrNone);
+		LogConfig(TheLogFile, TheCmdLineParams);
 		}
-#endif
-//
-	r=TheFs.MkDir(KTestDatabase);
-	test(r==KErrNone || r==KErrAlreadyExists);
-	}
+    }
+
+TInt E32Main()
+    {
+	TheTest.Title();
+
+	CTrapCleanup* tc = CTrapCleanup::New();
+	TheTest(tc != NULL);
 
-//
-// Initialise the cleanup stack.
-//
-LOCAL_C void setupCleanup()
-    {
-	TheTrapCleanup=CTrapCleanup::New();
-	test(TheTrapCleanup!=NULL);
-	TRAPD(r,\
-		{\
-		for (TInt i=KTestCleanupStack;i>0;i--)\
-			CleanupStack::PushL((TAny*)0);\
-		CleanupStack::Pop(KTestCleanupStack);\
-		});
-	test(r==KErrNone);
-	}
+	GetCmdLineParams(TheTest, _L("t_dbbench"), TheCmdLineParams);
+	_LIT(KDbName, "c:\\dbms-tst\\t_bench.db");
+	PrepareDbName(KDbName, TheCmdLineParams.iDriveName, TheDbFileName);
+	TheTest.Printf(_L("==Database: %S\r\n"), &TheDbFileName); 
 
-//
-// entry point
-//
-GLDEF_C TInt E32Main()
-    {
-	test.Title();
-	setupTestDirectory();
-	setupCleanup();
 	__UHEAP_MARK;
-//
-	test.Start(_L("Benchmarking..."));
-	TRAPD(r,BenchTestL());
-	test(r==KErrNone);
-	test.End();
-//
+	
+	TestEnvInit();
+	TRAPD(err, BenchTestL());
+	TEST2(err, KErrNone);
+	TestEnvDestroy();
+	
 	__UHEAP_MARKEND;
-	delete TheTrapCleanup;
 
-	//T_BENCH.DB cannot be deleted here, because it is used by T_COMP test!
-
-	TheFs.Close();
-	test.Close();
-	return 0;
+	User::Heap().Check();
+	
+	TheTest.End();
+	TheTest.Close();
+	
+	delete tc;
+	
+	return KErrNone;
     }