diff -r 000000000000 -r bde4ae8d615e os/kernelhwsrv/kerneltest/f32test/bench/t_fcachebm.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/kernelhwsrv/kerneltest/f32test/bench/t_fcachebm.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,1500 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// f32test/bench/t_fcachebm.cpp +// +// + +#include +#include +#include +#include "t_select.h" +#include "t_benchmain.h" + +//---------------------------------------------------------------------------------------------- +//! @SYMTestCaseID PBASE-T_RCACHE-0192 +//! @SYMTestType CIT +//! @SYMPREQ PREQ914 +//! @SYMTestCaseDesc This test case is testing performance of the File Server Cache. +//! @SYMTestActions 0 setup the environment to execute the tests +//! 1 small random reads/writes +//! 2 large sequential reads/writes +//! 3 streaming test (100, 200 and 500 kbps) +//! @SYMTestExpectedResults Finishes if the system behaves as expected, panics otherwise +//! @SYMTestPriority High +//! @SYMTestStatus Implemented +//---------------------------------------------------------------------------------------------- + + +GLDEF_D RTest test(_L("File Cache BM")); + +LOCAL_D RSemaphore client; +LOCAL_D const TInt KHeapSize = 0x4000; +LOCAL_D const TInt KTobps = 1000; +LOCAL_D const TInt KByte = 8; +LOCAL_D const TInt KOneSec = 1000000; // One second in microseconds + +// Tests setup +LOCAL_D const TInt KSmallRow = 11; +LOCAL_D const TInt KSmallCol = 7; +LOCAL_D const TInt KSmallThreshold = 64; +LOCAL_D const TInt KSeveralTimes = 10; + +LOCAL_D const TInt KLargeRow = 19; +LOCAL_D const TInt KLargeCol = 3; + +LOCAL_D TInt gCurrentSpeed = 0; +LOCAL_D TInt gCurrentBS = 0; + + +LOCAL_D TBuf8<4096> buf; +LOCAL_D TDriveList gDriveList; + +// Concurrent thread +RThread gSpeedy; +RThread gSpeedyII; + +TBuf16<25> gBaseFile; +TBuf16<25> gFileA; +TBuf16<25> gFileB; +TBuf16<25> gStreamFile; +TInt64 gMediaSize; + +HBufC8* gBuf = NULL; +TPtr8 gBufReadPtr(NULL, 0); +HBufC8* gBufSec = NULL; +TPtr8 gBufWritePtr(NULL, 0); + + +HBufC8* gBufB = NULL; +TPtr8 gBufReadBPtr(NULL, 0); +TBool gWriting = EFalse; + +LOCAL_D TInt ThreadCount=0; + +enum TTestState + { + ENoThreads, // No threads + ETwoThreadsDif, // Accessing to different files + ETwoThreadsDifDif, // Accessing to different files, different blocksizes + ETwoThreadsSame // Accessing the same file + }; + + +/** 2 ^ b + + @param b Power +*/ +LOCAL_C TInt Pow(TInt b) +{ + return 1 << b; +} + +/** Pseudo-random number generator, random enough for the purpose + + @param aMax Upper limit of the number. The interval of generated numbers is [0,aMax) +*/ +LOCAL_C TInt Rand(TInt aMax) +{ + return (Math::Random() % aMax); +} + + +/** Fills a buffer with character aC, aC+1, aC+2, ..., aC+32, aC, etc + + @param aBuffer Buffer to fill out + @param aLength Length to be filled with characters + @param aC Base character to fill the buffer +*/ +LOCAL_C void FillBuffer(TDes8& aBuffer, TInt aLength, TChar aC) + { + test (aBuffer.MaxLength() >= aLength); + + for(TInt i = 0; i < aLength; i++) + { + aBuffer.Append((i%32)+aC); + } + } + +/** Send content through the RDebug for trgtest + not to hung, when the test is not writing + +*/ +LOCAL_C TInt noise(TAny* ) +{ + FOREVER + { + User::After(2147483647); // max value, 35 minutes, 47 seconds + if(!gWriting) + RDebug::Print(_L(".")); + } +} + +/** Delete content of directory + + @param aDir Directory to be emptied +*/ +LOCAL_C TInt DeleteAll(TDes16& aDir) + { + TBuf16<100> dir; + CFileMan* fMan = CFileMan::NewL(TheFs); + TInt r = 0; + + dir = aDir; + dir.Append(_L("F*.*")); + r = fMan->Delete(dir); + + delete fMan; + return r; + } + + +/** Creates a file of aSize KBytes + + @param aFile File name + @param aSize Size of the file to be created +*/ +LOCAL_C void CreateFile(TDes16& aFile, TInt aSize) +{ + TInt r = 0; + RFile file; + + + r = file.Replace(TheFs, aFile, EFileShareAny|EFileWrite); + FailIfError(r); + + TInt j = 0; + while(j <= aSize) + { + r = file.Write(gBufWritePtr, KOneK); + FailIfError(r); + j += KOneK; + } + file.Close(); +} + +/** Kills the concurrent session + +*/ +LOCAL_C void DoTestKill() +{ + TInt r = 0; + + gSpeedy.Kill(KErrNone); + FailIfError(r); + gSpeedy.Close(); + + gSpeedyII.Kill(KErrNone); + FailIfError(r); + gSpeedyII.Close(); +} + +/** Read aSize KBs from aFile file in blocks of aBlockSize bytes + + @param aFile Name of the file + @param aPos Position from where the read starts within the file + @param aBlockSize Block size for the I/O operation + @param aSize +*/ +LOCAL_C TInt ReadFromFile(TDes16& aFile, TInt aPos, TInt aBlockSize, TInt aSize) +{ + TInt r = 0; + TTime startTime; + TTime endTime; + RFile file; + TInt j = 0; + TInt size = aSize * KOneK; + TTimeIntervalMicroSeconds timeTaken(0); + + r = file.Open(TheFs,aFile,EFileShareAny|EFileRead); + FailIfError(r); + + startTime.HomeTime(); + r = file.Seek(ESeekStart, aPos); + FailIfError(r); + + while(j <= size) + { + r = file.Read(gBufReadPtr, aBlockSize); + FailIfError(r); + j += aBlockSize; + } + endTime.HomeTime(); + + file.Close(); + timeTaken = endTime.MicroSecondsFrom(startTime); + + return I64LOW(timeTaken.Int64() / gTimeUnit); +} + +/** Read aSize KBs from aFile file in blocks of aBlockSize bytes several times + + @param aFile Name of the file + @param ayMax Maximum for the position + @param aBlockSize Block size for the I/O operation + @param aSize Size of the file in KB +*/ +LOCAL_C TInt ReadFromFileSeveralTimes(TDes16& aFile, TInt ayMax, TInt aBlockSize, TInt aSize) +{ + TInt r = 0; + TTime startTime; + TTime endTime; + RFile file; + TInt j = 0, i, pos; + TInt size = aSize * KOneK; + TTimeIntervalMicroSeconds timeTaken(0); + TInt64 time = 0; + + + r = file.Open(TheFs, aFile, EFileShareAny|EFileRead); + FailIfError(r); + + i = 0; + while( i < KSeveralTimes ) + { + pos = Rand(Pow(ayMax - 1)); + startTime.HomeTime(); + r = file.Seek(ESeekStart, pos); + FailIfError(r); + + j = 0; + while(j <= size) + { + r = file.Read(gBufReadPtr, aBlockSize); + FailIfError(r); + j += aBlockSize; + } + endTime.HomeTime(); + + timeTaken = endTime.MicroSecondsFrom(startTime); + time += I64LOW(timeTaken.Int64()); + i++; + } + + file.Close(); + + return I64LOW((time / gTimeUnit) / KSeveralTimes); // Overflow not expected here, since the number is not big enough +} + + +/** Write aSize KBs to aFile file in blocks of aBlockSize bytes + + @param aFile Name of the file + @param aPos Position from where the read starts within the file + @param aBlockSize Block size for the I/O operation + @param aSize Size of the file in KB +*/ +LOCAL_C TInt WriteToFile(TDes16& aFile, TInt aPos, TInt aBlockSize, TInt aSize) +{ + TInt r = 0; + TTime startTime; + TTime endTime; + RFile file; + TInt j = 0; + TInt size = aSize * KOneK; + TTimeIntervalMicroSeconds timeTaken(0); + + r = file.Open(TheFs, aFile, EFileShareAny|EFileWrite); + FailIfError(r); + + startTime.HomeTime(); + r = file.Seek(ESeekStart, aPos); + FailIfError(r); + while(j <= size) + { + r = file.Write(gBufWritePtr, aBlockSize); + FailIfError(r); + j += aBlockSize; + } + endTime.HomeTime(); + + file.Close(); + timeTaken = endTime.MicroSecondsFrom(startTime); + + return I64LOW(timeTaken.Int64() / gTimeUnit); +} + +/** Write aSize KBs to aFile file in blocks of aBlockSize bytes several times + + @param aFile Name of the file + @param ayMax Maximum for the position + @param aBlockSize Block size for the I/O operation + @param aSize Size of the file in KB +*/ +LOCAL_C TInt WriteToFileSeveralTimes(TDes16& aFile, TInt ayMax, TInt aBlockSize, TInt aSize) +{ + TInt r = 0; + TTime startTime; + TTime endTime; + RFile file; + TInt i, j = 0, pos; + TInt size = aSize * KOneK; + TTimeIntervalMicroSeconds timeTaken(0); + TInt64 time = 0; + + r = file.Open(TheFs, aFile, EFileShareAny|EFileWrite); + FailIfError(r); + + i = 0; + while( i < KSeveralTimes ) + { + pos = Rand(Pow(ayMax - 1)); + startTime.HomeTime(); + r = file.Seek(ESeekStart, pos); + FailIfError(r); + + j = 0; + while(j <= size) + { + r = file.Write(gBufWritePtr, aBlockSize); + FailIfError(r); + j += aBlockSize; + } + endTime.HomeTime(); + + timeTaken = endTime.MicroSecondsFrom(startTime); + time += I64LOW(timeTaken.Int64()); + i++; + } + + file.Close(); + + return I64LOW((time / gTimeUnit) / KSeveralTimes); // Overflow not expected here, since the number is not big enough +} + +/** Read small blocks in the gBaseFile + +*/ +LOCAL_C TInt ReadSmallBase(TAny* ) +{ + RTest test(_L("test 2")); + RFs fs; + RFile file; + TBuf8<1024> dummy(1024); + TInt blockSize = 0; + TInt randPos = 0; + TInt i = 0; + + TInt r = fs.Connect(); + + fs.SetSessionPath(gSessionPath); + r = file.Open(fs, gBaseFile, EFileShareAny|EFileRead); + client.Signal(); + + FailIfError(r); + + FOREVER + { + randPos = Rand(64) * KOneK ; + r = file.Seek(ESeekStart, randPos); + FailIfError(r); + blockSize = i; + + r = file.Read(dummy, blockSize); // Sync operation + if(i >= 1023) i = 0; + else i++; + } +} + +/** Read small blocks in gFileA + +*/ +LOCAL_C TInt ReadSmallA(TAny* ) +{ + RTest test(_L("test 2")); + RFs fs; + RFile file; + TInt blockSize = 0; + TInt randPos = 0; + TBuf8<1024> dummy(1024); + TInt i = 0; + + TInt r = fs.Connect(); + + fs.SetSessionPath(gSessionPath); + + r = file.Open(fs,gFileA,EFileShareAny|EFileRead); + + client.Signal(); + FailIfError(r); + + FOREVER + { + randPos = Rand(64) * KOneK ; + r = file.Seek(ESeekStart, randPos); + FailIfError(r); + + blockSize = i; + + r = file.Read(dummy, blockSize); // Sync operation + FailIfError(r); + if(i >= 1023) i = 0; + else i++; + } +} + +/** Read small blocks in gFileB + +*/ +LOCAL_C TInt ReadSmallB(TAny* ) + { + RTest test(_L("test 2")); + RFs fs; + RFile file; + TBuf8<1024> dummy(1024); + TInt blockSize = 0; + TInt randPos = 0; + TInt i = 0; + + TInt r = fs.Connect(); + + fs.SetSessionPath(gSessionPath); + r = file.Open(fs, gFileB, EFileShareAny|EFileRead); + + client.Signal(); + FailIfError(r); + + FOREVER + { + randPos = Rand(64) * KOneK ; + r = file.Seek(ESeekStart, randPos); + FailIfError(r); + blockSize = i; + + r = file.Read(dummy, blockSize); // Sync operation + FailIfError(r); + if(i >= 1023) i = 0; + else i++; + } +} + + +/** Read large blocks in gBaseFile + +*/ +LOCAL_C TInt ReadLargeBase(TAny* ) + { + RTest test(_L("test 2")); + RFs fs; + RFile file; + TInt pos = 0; + TInt blockSize = 128 * KOneK; + + TInt r = fs.Connect(); + + fs.SetSessionPath(gSessionPath); + r = file.Open(fs,gBaseFile,EFileShareAny|EFileRead); + + client.Signal(); + FailIfError(r); + + FOREVER + { + r = file.Seek(ESeekStart, pos); + FailIfError(r); + + r = file.Read(gBufReadBPtr, blockSize); // Sync operation + FailIfError(r); + } +} + +/** Read large blocks in gFileA + +*/ +LOCAL_C TInt ReadLargeA(TAny* ) +{ + RTest test(_L("test 2")); + RFs fs; + RFile file; + TInt blockSize = 128 * KOneK; + TInt pos = 0; + + TInt r = fs.Connect(); + + fs.SetSessionPath(gSessionPath); + + r = file.Open(fs,gFileA,EFileShareAny|EFileRead); + + client.Signal(); + FailIfError(r); + + FOREVER + { + r = file.Seek(ESeekStart, pos); + FailIfError(r); + + r = file.Read(gBufReadBPtr, blockSize); // Sync operation + FailIfError(r); + } +} + +/** Read large blocks in gFileB + +*/ +LOCAL_C TInt ReadLargeB(TAny* ) +{ + RTest test(_L("test 2")); + RFs fs; + RFile file; + TInt blockSize = 128 * KOneK; + TInt pos = 0; + + TInt r=fs.Connect(); + FailIfError(r); + + fs.SetSessionPath(gSessionPath); + + r = file.Open(fs,gFileB,EFileShareAny|EFileRead); + + client.Signal(); + FailIfError(r); + + FOREVER + { + r = file.Seek(ESeekStart, pos); + FailIfError(r); + + r = file.Read(gBufReadBPtr, blockSize); // Sync operation + FailIfError(r); + } +} + +/** Small reads from a file + + @param xMax Maximum position on the x axe + @param yMax Maximum position on the y axe + @param aCase Type of test. Possible values: + - ENoThreads : isolated + - ETwoThreadsSame : with two threads accessing same file + - ETwoThreadsDif : with two threads accessing dif. files +*/ +LOCAL_C void smallReads(TInt xMax, TInt yMax, TTestState aCase) + { + TInt i = 0; + TInt j = 0; + TInt r = 0; + TInt timeRes = 0; + + CreateFile(gBaseFile, Pow(yMax-1)); + + if(aCase == ETwoThreadsSame) + { // Start two different threads accessing the same file + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + if(aCase == ETwoThreadsDif) + { // Start two different threads accessing different files + CreateFile(gFileA, Pow(yMax-1)); + CreateFile(gFileB, Pow(yMax-1)); + + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadSmallA, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadSmallB, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + while(i < xMax) + { // Actual accesses and timing to the main file + j = 0; + PrintResult(i + 1, j + 1, Pow(i)); + while(j < yMax) + { + if(Pow(i) < KSmallThreshold) + { + timeRes = ReadFromFile(gBaseFile, Rand(Pow(yMax - 1)), Pow(i), Pow(j)); + } + else + { // Too small for only one time measure + timeRes = ReadFromFileSeveralTimes(gBaseFile, yMax, Pow(i), Pow(j)); + } + + gWriting = ETrue; + User::After(1000000); + + PrintResultTime(i + 1, j + 2, timeRes); + + gWriting = EFalse; + + j++; + } + i++; + } + + + if((aCase == ETwoThreadsSame) || (aCase == ETwoThreadsDif)) + { // Finish the threads + DoTestKill(); + } + } + +/** Large reads from a file + + @param xMax Maximum position on the x axe + @param yMax Maximum position on the y axe + @param aCase Type of test. Possible values: + - ENoThreads : isolated + - ETwoThreadsSame : with two threads accessing same file + - ETwoThreadsDif : with two threads accessing dif. files + - ETwoThreadsDifDif : with two threads accessing dif. files, different block sizes (big/small) +*/ +LOCAL_C void largeReads(TInt xMax, TInt yMax, TTestState aCase) +{ + TInt i = 0; + TInt j = 0; + TInt r = 0; + TInt timeRes = 0; + + CreateFile(gBaseFile, 10 * KOneK * KOneK); // 10 Mb + + if(aCase == ETwoThreadsSame) + { // Start two different threads accessing the same file + + TRAPD(res, gBufB = HBufC8::NewL(256 * KOneK)); + test(res == KErrNone && gBufB != NULL); + gBufReadBPtr.Set(gBufSec->Des()); + + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadLargeBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadLargeBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + if(aCase == ETwoThreadsDif) + { // Start two different threads accessing different files + + CreateFile(gFileA, KOneK * KOneK); + CreateFile(gFileB, KOneK * KOneK); + + TRAPD(res, gBufB = HBufC8::NewL(256 * KOneK)); + test(res == KErrNone && gBufB != NULL); + gBufReadBPtr.Set(gBufSec->Des()); + + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadLargeA, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadLargeB, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + if(aCase == ETwoThreadsDifDif) + { // Start two different threads accessing different files + + CreateFile(gFileA, KOneK * KOneK); + CreateFile(gFileB, KOneK * KOneK); + + TRAPD(res,gBufB = HBufC8::NewL(256 * KOneK)); + test(res == KErrNone && gBufB != NULL); + gBufReadBPtr.Set(gBufSec->Des()); + + TBuf<20> buf=_L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadLargeA, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadSmallB, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + i = 11; + while(i < xMax ) + { // Actual accesses and timing to the main file + j = 0; + PrintResult(i - 10, j + 1, Pow(i)); + while(j < yMax) + { + TInt size=0; + if(j == 0) size = 100 ; // 100 Kb + if(j == 1) size = KOneK ; // 1 Mb + if(j == 2) size = 10 * KOneK ; // 10 Mb + + timeRes = ReadFromFile(gBaseFile, 0, Pow(i), size); + + gWriting = ETrue; + User::After(1000000); + + PrintResultTime(i - 10, j + 2, timeRes); + + gWriting = EFalse; + + j++; + } + i++; + } + + if((aCase == ETwoThreadsSame) || (aCase == ETwoThreadsDif) || (aCase == ETwoThreadsDifDif)) + { // Finish the threads + DoTestKill(); + delete gBufB; + } + +} + +/** Large writes to a file + + @param xMax Maximum position on the x axe + @param yMax Maximum position on the y axe + @param aCase Type of test. Possible values: + - ENoThreads : isolated + - ETwoThreadsSame : with two threads accessing same file + - ETwoThreadsDif : with two threads accessing dif. files +*/ +LOCAL_C void largeWrites(TInt xMax, TInt yMax, TTestState aCase) +{ + TInt i = 0; + TInt j = 0; + TInt r = 0; + TInt timeRes = 0; + + CreateFile(gBaseFile, 10 * KOneK * KOneK); // 10 Mb + + if(aCase == ETwoThreadsSame) + { // Start two different threads accessing the same file + + TRAPD(res, gBufB = HBufC8::NewL(256 * KOneK)); + test(res == KErrNone && gBufB != NULL); + gBufReadBPtr.Set(gBufSec->Des()); + + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadLargeBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadLargeBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + if(aCase == ETwoThreadsDif) + { // Start two different threads accessing different files + + CreateFile(gFileA, KOneK * KOneK); + CreateFile(gFileB, KOneK * KOneK); + + TRAPD(res, gBufB = HBufC8::NewL(256 * KOneK)); + test(res == KErrNone && gBufB != NULL); + gBufReadBPtr.Set(gBufSec->Des()); + + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadLargeA, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadLargeB, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + i = 11; + while(i < xMax ) + { // Actual accesses and timing to the main file + j = 0; + PrintResult(i - 10 , j + 1, Pow(i)); + while(j < yMax) + { + TInt size=0; + if(j == 0) size = 100 ; // 100 Kb + if(j == 1) size = KOneK ; // 1 Mb + if(j == 2) size = 10 * KOneK ; // 10 Mb + timeRes = WriteToFile(gBaseFile, 0, Pow(i), size); + + gWriting = ETrue; + User::After(1000000); + + PrintResultTime(i - 10, j + 2, timeRes); + + gWriting = EFalse; + j++; + } + i++; + } + + if((aCase == ETwoThreadsSame) || (aCase == ETwoThreadsDif) || (aCase == ETwoThreadsDifDif)) + { // Finish the threads + DoTestKill(); + delete gBufB; + } + +} + +/** Small writes to a file + + @param xMax Maximum position on the x axe + @param yMax Maximum position on the y axe + @param aCase Type of test. Possible values: + - ENoThreads : isolated + - ETwoThreadsSame : with two threads accessing same file + - ETwoThreadsDif : with two threads accessing dif. files +*/ +LOCAL_C void smallWrites(TInt xMax, TInt yMax, TTestState aCase) +{ + TInt i = 0; + TInt j = 0; + TInt r = 0; + TInt timeRes = 0; + + CreateFile(gBaseFile, Pow(yMax-1)); + + if(aCase == ETwoThreadsSame) + { // Start two different threads accessing the same file + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + if(aCase == ETwoThreadsDif) + { // Start two different threads accessing different files + CreateFile(gFileA, Pow(yMax-1)); + CreateFile(gFileB, Pow(yMax-1)); + + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + r = gSpeedy.Create(buf, ReadSmallA, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + r = gSpeedyII.Create(buf, ReadSmallB, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + gSpeedyII.Resume(); + + client.Wait(); + client.Wait(); + } + + while(i < xMax) + { + j = 0; + PrintResult(i + 1, j + 1, Pow(i)); + while(j < yMax) + { + if(Pow(i) < KSmallThreshold) + { + timeRes = WriteToFile(gBaseFile, Rand(Pow(yMax-1)), Pow(i), Pow(j)); + } + else + { + timeRes = WriteToFileSeveralTimes(gBaseFile, yMax, Pow(i), Pow(j)); + } + + gWriting = ETrue; + User::After(1000000); + + PrintResultTime(i + 1, j + 2, timeRes); + + gWriting = EFalse; + + j++; + } + i++; + } + + if((aCase == ETwoThreadsSame) || (aCase == ETwoThreadsDif)) + { // Finish the threads + DoTestKill(); + } + +} + +/** This test benchmarks small random r/w (e.g. database access) + + @param aSelector Selection array for manual tests +*/ +LOCAL_C TInt TestSmall(TAny* aSelector) +{ + + Validate(aSelector); + + // Each test case of the suite has an identifyer for parsing purposes of the results + gTestHarness = 7; + gTestCase = 1; + gTimeUnit = 1; + + PrintHeaders(4, _L("t_fcachebm. Small Random r/w")); + + // Small reads + test.Printf(_L("#~TS_Title_%d,%d: Small reads, no threads \n"), gTestHarness, gTestCase); + + smallReads(KSmallRow, KSmallCol, ENoThreads); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Small reads, threads accessing same file \n"), + gTestHarness, gTestCase); + + smallReads(KSmallRow, KSmallCol, ETwoThreadsSame); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Small reads, threads accessing dif files \n"), + gTestHarness, gTestCase); + + smallReads(KSmallRow, KSmallCol, ETwoThreadsDif); + + gTestCase++; + DeleteAll(gSessionPath); + + // Small writes test case + + test.Printf(_L("#~TS_Title_%d,%d: Test small writes\n"), gTestHarness, gTestCase); + + smallWrites(KSmallRow, KSmallCol, ENoThreads); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Small writes, threads accessing same file \n"), + gTestHarness, gTestCase); + smallWrites(KSmallRow, KSmallCol, ETwoThreadsSame); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Small writes, threads accessing dif files \n"), + gTestHarness, gTestCase); + smallWrites(KSmallRow, KSmallCol, ETwoThreadsDif); + + gTestCase++; + DeleteAll(gSessionPath); + test.Printf(_L("#~TestEnd_%d\n"), gTestHarness); + + return(KErrNone); +} + +/** This test benchmarks large sequential r/w (e.g. MM) + + @param aSelector Selection array for manual tests +*/ +LOCAL_C TInt TestLarge(TAny* aSelector) +{ + + Validate(aSelector); + + // Each test case of the suite has an identifyer for parsing purposes of the results + gTestHarness = 8; + gTestCase = 1; + gTimeUnit = 1000; + + PrintHeaders(3, _L("t_fcachebm. Large sequential r/w")); + + // Large reads + test.Printf(_L("#~TS_Title_%d,%d: Large sequential reads\n"), gTestHarness, gTestCase); + + largeReads(KLargeRow, KLargeCol, ENoThreads); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Large sequential reads, threads accessing same file\n"), + gTestHarness, gTestCase); + largeReads(KLargeRow, KLargeCol, ETwoThreadsSame); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Large sequential reads, threads accessing dif files\n"), + gTestHarness, gTestCase); + largeReads(KLargeRow, KLargeCol, ETwoThreadsDif); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Large sequential reads, threads accessing dif files some big some small blocks\n"), + gTestHarness, gTestCase); + largeReads(KLargeRow, KLargeCol, ETwoThreadsDifDif); + + gTestCase++; + DeleteAll(gSessionPath); + + // Large writings + test.Printf(_L("#~TS_Title_%d,%d: Large sequential writes\n"), gTestHarness, gTestCase); + + largeWrites(KLargeRow, KLargeCol, ENoThreads); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Large sequential writes, threads accessing same file\n"), + gTestHarness, gTestCase); + largeWrites(KLargeRow, KLargeCol, ETwoThreadsSame); + + gTestCase++; + test.Printf(_L("#~TS_Title_%d,%d: Large sequential writes, threads accessing dif files\n"), + gTestHarness, gTestCase); + largeWrites(KLargeRow, KLargeCol, ETwoThreadsDif); + + gTestCase++; + DeleteAll(gSessionPath); + test.Printf(_L("#~TestEnd_%d\n"), gTestHarness); + + return(KErrNone); +} + +/** Writes aSize bytes of data in aBlockSize during aTime seconds + if the aSize bps is not met, it fails + + @param f File to write to + @param aSize Size in bytes of data to be written + @param aBlockSize Block size to be used + @param aTime Time during which the write has to happen in seconds +*/ +LOCAL_C TBool writeStr( RFile f, TInt aSize, TInt aBlockSize, TInt aTime) +{ + TInt r = 0, j = 0; + TTime startTime, endTime; + TTimeIntervalMicroSeconds timeTaken(0); + TTimeIntervalMicroSeconds32 timeLeft(0); + TBool onTarget = ETrue; + + TInt time; + + TInt i = 0; + while((i < aTime) && onTarget) + { + // If measuring the CPU time + + startTime.HomeTime(); + j = 0; + while(j < aSize) + { + r = f.Write(gBufWritePtr, aBlockSize); + FailIfError(r); + j += aBlockSize; + } + endTime.HomeTime(); + + timeTaken = endTime.MicroSecondsFrom(startTime); + time = I64LOW(timeTaken.Int64()); + if(time > KOneSec) + { + onTarget = EFalse; + } + + timeLeft = KOneSec - time; + if(timeLeft.Int() >= 0) + { + User::After(timeLeft); + } + i++; + } + + return onTarget; +} + +/** Reads streaming + +*/ +LOCAL_C TInt ReadStream(TAny*) +{ + RTest test(_L("test 2")); + RFs fs; + RFile file; + TInt j = 0; + TTime startTime, endTime; + TTimeIntervalMicroSeconds timeTaken(0); + TTimeIntervalMicroSeconds32 timeLeft(0); + TInt time; + TInt size , currentPos = 0; + + TInt r = fs.Connect(); + + fs.SetSessionPath(gSessionPath); + + r = file.Open(fs, gStreamFile, EFileShareAny|EFileRead); + + client.Signal(); + + FailIfError(r); + r = file.Size(size); + FailIfError(r); + + FOREVER + { + startTime.HomeTime(); + j = 0; + while(j < (gCurrentSpeed * KOneK)) + { + r=file.Read(gBufReadPtr,gCurrentBS); + FailIfError(r); + j += gCurrentBS; + } + endTime.HomeTime(); + + timeTaken = endTime.MicroSecondsFrom(startTime); + time = I64LOW(timeTaken.Int64()); + + if(time > KOneSec) + { + test.Printf(_L("Background Thread: Speed failed to be achieved: %d kbps\n"), gCurrentSpeed); + } + + + + timeLeft = KOneSec - time; + User::After(timeLeft); + currentPos += (gCurrentSpeed * KOneK); + r = file.Size(size); + FailIfError(r); + if(currentPos > size ) + { + currentPos = 0; + file.Seek(ESeekStart, currentPos); + } + + } + +} + +/** Test case layout, read/write at aSpeed during aWtime and aRTime + + @param aSpeed Target speed in kbps + @param aBlockSize Block size for the I/O operation + @param aWTime Writing time + @param aRTime Reading time +*/ +LOCAL_C void streamIt ( TInt aSpeed, TInt aBlockSize, TInt aWTime, TInt aRTime, TInt aStep) +{ + TInt iSize = (aSpeed * KTobps) / KByte; // Size in bytes + RFile file; + TInt pos = 0; + TInt r = 0; + + PrintResult(aStep, 1, aBlockSize); + + r = file.Replace(TheFs, gStreamFile, EFileShareAny|EFileWrite); + FailIfError(r); + + // Streaming to the media during aWTime seconds + if(writeStr(file, iSize, aBlockSize, aWTime)) + { //Pass (1) + PrintResult(aStep, 2, 1); + } + else + { //Fail (0) + PrintResult(aStep, 2, 0); + } + + // Create a different thread for reading from the beginning during aRTime + TBuf<20> buf = _L("Speedy"); + buf.AppendNum(ThreadCount++); + + gCurrentSpeed = aSpeed; + gCurrentBS = aBlockSize; + r = gSpeedy.Create(buf, ReadStream, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedy.Resume(); + client.Wait(); + + // Keep writing during the time the other thread is reading + if(writeStr(file, iSize, aBlockSize, aRTime)) + { //Pass (1) + PrintResult(aStep, 3, 1); + } + else + { //Fail (0) + PrintResult(aStep, 3, 0); + } + + // Writing from the beginning again + file.Seek(ESeekStart, pos); + if(writeStr(file, iSize, aBlockSize, aRTime)) + { //Pass (1) + PrintResult(aStep, 4, 1); + } + else + { //Fail (0) + PrintResult(aStep, 4, 0); + } + + + // Kill the thread for reading + gSpeedy.Kill(KErrNone); + FailIfError(r); + gSpeedy.Close(); + + file.Close(); +} + +/** Iterating through different blocksizes + + @param aSpeed Speed at which the test happens +*/ +LOCAL_C void streaming(TInt aSpeed) +{ + TInt i = 9; // Pow(i) = 512 bytes + TInt blockSize = 0; + TInt testStep = 1; + + while( i < 15 ) // Pow(i) = 16 Kb + { + blockSize = Pow(i) ; + streamIt(aSpeed, blockSize, 5 * 60, 15, testStep++); // 5 minutes writing , then 15 secs reading + i++; + } +} + +/** High level test routine. Different test cases executed + + @param aSelector Test case configuration in case of manual execution +*/ +LOCAL_C TInt TestStreaming(TAny* aSelector) +{ + + Validate(aSelector); + // Each test case of the suite has an identifyer for parsing purposes of the results + gTestHarness = 9; + gTestCase = 1; + + + PrintHeaders(5, _L("t_fcachebm. Streaming")); + + test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 100 kbps\n"), + gTestHarness, gTestCase); + + streaming(100); + + test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 200 kbps\n"), + gTestHarness, ++gTestCase); + + streaming(200); + + test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 500 kbps\n"), + gTestHarness, ++gTestCase); + + streaming(500); + + + DeleteAll(gSessionPath); + + // Start the small random reads in the background + CreateFile(gBaseFile, Pow(KSmallCol-1)); + + TBuf<20> buf=_L("Speedy"); + buf.AppendNum(ThreadCount++); + + TInt r = gSpeedyII.Create(buf, ReadSmallBase, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + gSpeedyII.Resume(); + client.Wait(); + + // Measure the throughput with background activity + test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 100 kbps, while small reads\n"), + gTestHarness, ++gTestCase); + + streaming(100); + + test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 200 kbps, while small reads\n"), + gTestHarness, ++gTestCase); + + streaming(200); + + test.Printf(_L("#~TS_Title_%d,%d: Writing / reading at 500 kbps, while small reads\n"), + gTestHarness, ++gTestCase); + + streaming(500); + + // Kill the small random reads and writes + gSpeedyII.Kill(KErrNone); + FailIfError(r); + + gSpeedyII.Close(); + + DeleteAll(gSessionPath); + + gTestCase++; + test.Printf(_L("#~TestEnd_%d\n"), gTestHarness); + + return(KErrNone); +} + +/** It goes automatically through all the options + + @param aSelector Configuration in case of manual execution +*/ +LOCAL_C TInt TestAll(TAny* aSelector) +{ + TestSmall(aSelector); + TestLarge(aSelector); + TestStreaming(aSelector); + + return(KErrNone); +} + +/** Call all tests + +*/ +GLDEF_C void CallTestsL() +{ + TBuf16<25> temp; + + TInt r=client.CreateLocal(0); + FailIfError(r); + + // Setting up the environment and creating the needed files + gSessionPath = _L("?:\\F32-TST\\"); + gSessionPath[0] = (TText) gDriveToTest; + + FileNamesGeneration(temp, 8, 0, 1); + gBaseFile = gSessionPath; + gBaseFile.Append(temp); + + FileNamesGeneration(temp, 8, 1, 1); + gFileA = gSessionPath; + gFileA.Append(temp); + + FileNamesGeneration(temp, 8, 2, 1); + gFileB = gSessionPath; + gFileB.Append(temp); + + FileNamesGeneration(temp, 8, 3, 1); + gStreamFile = gSessionPath; + gStreamFile.Append(temp); + + TRAPD(res,gBuf = HBufC8::NewL(256 * KOneK)); + test(res == KErrNone && gBuf != NULL); + + gBufWritePtr.Set(gBuf->Des()); + FillBuffer(gBufWritePtr, 256 * KOneK, 'A'); + + TRAPD(res2, gBufSec = HBufC8::NewL(256 * KOneK)); + test(res2 == KErrNone && gBufSec != NULL); + gBufReadPtr.Set(gBufSec->Des()); + + TVolumeInfo volInfo; + TInt drive; + + r = TheFs.CharToDrive(gDriveToTest,drive); + FailIfError(r); + r = TheFs.Volume(volInfo, drive); + FailIfError(r); + + gMediaSize = volInfo.iSize; + + FormatFat(gSessionPath[0]-'A'); + TheFs.MkDirAll(gSessionPath); + + RThread noisy; + TBuf<20> buf = _L("Noisy"); + r = noisy.Create(buf, noise, KDefaultStackSize, KHeapSize, KHeapSize, NULL); + FailIfError(r); + + noisy.Resume(); + + CSelectionBox* TheSelector=CSelectionBox::NewL(test.Console()); + + if(gMode == 0) + { // Manual + gSessionPath=_L("?:\\"); + TCallBack smallOps(TestSmall, TheSelector); + TCallBack largeOps(TestLarge, TheSelector); + TCallBack simulOps(TestStreaming, TheSelector); + TCallBack tAll(TestAll, TheSelector); + TheSelector->AddDriveSelectorL(TheFs); + TheSelector->AddLineL(_L("Small random r/w"), smallOps); + TheSelector->AddLineL(_L("Large conseq r/w"), largeOps); + TheSelector->AddLineL(_L("Streaming"), simulOps); + TheSelector->AddLineL(_L("Execute all options"), tAll); + TheSelector->Run(); + } + else + { // Automatic + TestAll(TheSelector); + } + + DeleteAll(gSessionPath); + + client.Close(); + delete TheSelector; + delete gBuf; + delete gBufSec; + noisy.Kill(KErrNone); + noisy.Close(); +}