sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\bench\t_membm.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #define ALIGN_UP(x, y) (TInt8*)(_ALIGN_UP((TInt)(x), (y))) sl@0: #define ALIGN_DOWN(x, y) (TInt8*)(_ALIGN_DOWN((TInt)(x), (y))) sl@0: sl@0: const TInt KHeapSize=720*1024; sl@0: const TInt KAverageOverInMilliseconds=500; sl@0: const TInt Len64K = 64*1024; sl@0: sl@0: volatile TInt count; sl@0: volatile TInt iters; sl@0: sl@0: TInt8* trg; sl@0: TInt8* src; sl@0: TInt8* dummy; sl@0: TInt8 trgoffset; sl@0: TInt8 srcoffset; sl@0: TInt len=64*1024; sl@0: TInt64 result; sl@0: sl@0: RTest test(_L("T_MEMBM")); sl@0: sl@0: GLREF_C TInt MemBaseline(TAny*); sl@0: GLREF_C TInt MemCopy(TAny*); sl@0: GLREF_C TInt MemMove(TAny*); sl@0: GLREF_C TInt MemFill(TAny*); sl@0: GLREF_C TInt MemSwap(TAny*); sl@0: GLREF_C TInt WordMove(TAny*); sl@0: GLREF_C TInt MemCopyUncached(TAny*); sl@0: GLREF_C TInt WordMoveUncached(TAny*); sl@0: GLREF_C TInt MemFillUncached(TAny*); sl@0: GLREF_C TInt PurgeCache(); sl@0: sl@0: TInt nextLen(TInt aTestLength) sl@0: { sl@0: if (len == Len64K) sl@0: return 0; sl@0: if (!aTestLength) sl@0: return Len64K; sl@0: sl@0: TInt inc = aTestLength; sl@0: for (TInt i = len >> 5 ; i ; i >>= 1) sl@0: inc <<= 1; sl@0: sl@0: return len + inc; sl@0: } sl@0: sl@0: /** sl@0: * Run benchmarks on the supplied function. sl@0: * sl@0: * @param aFunction The function to benchmark sl@0: * @param aTestBackwards Run copy tests with overlapping areas to test backwards copy sl@0: * @param aTestSrcAlign Run tests for source alignments 0 - 31 sl@0: * @param aTestDestAlign Run tests for destination alignments 0 - 31 sl@0: * @param aTestLength If non-zero, run tests for different lengths starting at aTestLength sl@0: */ sl@0: TInt64 runTest(TThreadFunction aFunction,const TDesC& aTitle, TBool aTestBackwards, TBool aTestSrcAlign, TBool aTestDestAlign, TInt aTestLength) sl@0: { sl@0: TInt8* buffer = (TInt8*)User::Alloc(640 * 1024 + 32); sl@0: test(buffer != 0); sl@0: sl@0: test(!(aTestLength && aTestBackwards)); // not supported sl@0: sl@0: TBool goingforward=ETrue; sl@0: sl@0: FOREVER sl@0: { sl@0: if (aTestLength) sl@0: test.Printf(_L("Running length experiment on %S. Results follow:\n"), &aTitle); sl@0: sl@0: len = 0; sl@0: while(len = nextLen(aTestLength), len) sl@0: { sl@0: src = ALIGN_UP(buffer, 32); sl@0: if (goingforward) sl@0: trg = src + 512 * 1024; // blow half a meg sl@0: else sl@0: trg = ALIGN_DOWN(src + len - 1, 32); // ensure overlapping, doesn't work for length < 32 sl@0: sl@0: if (aTestLength) sl@0: test.Printf(_L("%d, "), len); sl@0: else sl@0: test.Printf(_L("Test array bases trg=0x%08x, src=0x%08x. Running experiment on %S. Results follow:\n"), trg, src, &aTitle); sl@0: sl@0: const TInt xsquare = aTestDestAlign ? 32 : 1; sl@0: const TInt ysquare = aTestSrcAlign ? 32 : 1; sl@0: sl@0: for (srcoffset = 0 ; srcoffset < ysquare ; srcoffset++) sl@0: { sl@0: for (trgoffset = 0 ; trgoffset < xsquare ; trgoffset++) sl@0: { sl@0: RThread thread; sl@0: TInt r=thread.Create(aTitle,aFunction,KDefaultStackSize,KHeapSize,KHeapSize,NULL); sl@0: if(r!=KErrNone) sl@0: { sl@0: test.Printf(_L("Failed to create thread with error %d\n"),r); sl@0: return(r); sl@0: } sl@0: thread.SetPriority(EPriorityLess); sl@0: thread.Resume(); sl@0: User::After(50000); // 50 msec is more than enough in EKA2 sl@0: count=0; sl@0: User::After(5000); // even if the second reset fails, max inaccuracy is 5000 usecs sl@0: count=0; // try and reduce the probability of failing to reset sl@0: User::After(KAverageOverInMilliseconds*1000); sl@0: result=count; sl@0: thread.Kill(0); sl@0: CLOSE_AND_WAIT(thread); sl@0: PurgeCache(); sl@0: sl@0: result *= 1000; sl@0: result /= KAverageOverInMilliseconds; sl@0: sl@0: TInt s = I64INT(result); sl@0: test.Printf(_L("%d, "),s); sl@0: } sl@0: test.Printf(_L("\n")); sl@0: } sl@0: } sl@0: sl@0: if (aTestBackwards && goingforward) sl@0: goingforward = EFalse; sl@0: else sl@0: break; sl@0: } sl@0: sl@0: User::Free(buffer); sl@0: sl@0: return(result); sl@0: } sl@0: sl@0: enum TTestType sl@0: { sl@0: ENormalTests, sl@0: EFullTests, sl@0: ELengthTests, sl@0: }; sl@0: sl@0: // Return whether we should run the full alignment benchmarks sl@0: TTestType ParseCommandLine() sl@0: { sl@0: TBuf<32> args; sl@0: User::CommandLine(args); sl@0: sl@0: if (args == _L("-f")) sl@0: return EFullTests; sl@0: else if (args == _L("-l")) sl@0: return ELengthTests; sl@0: else if (args != KNullDesC) sl@0: { sl@0: test.Printf(_L("usage: t_membm [OPTIONS]\n")); sl@0: test.Printf(_L(" -f Run full alignment benchmarks\n")); sl@0: test.Printf(_L(" -l Run memcpy length benchmarks\n")); sl@0: test(EFalse); sl@0: } sl@0: sl@0: return ENormalTests; sl@0: } sl@0: sl@0: TInt E32Main() sl@0: // sl@0: // Benchmark for Mem functions sl@0: // sl@0: { sl@0: sl@0: test.Title(); sl@0: test.Start(_L("Benchmarks for Mem functions")); sl@0: sl@0: TTestType testType = ParseCommandLine(); sl@0: sl@0: switch (testType) sl@0: { sl@0: case ENormalTests: sl@0: case EFullTests: sl@0: { sl@0: TBool srcAlign = testType == EFullTests; sl@0: sl@0: if (srcAlign) sl@0: test.Printf(_L("Running full alignment benchmarks (may take a long time)\n")); sl@0: else sl@0: test.Printf(_L("Not testing source alignment (run with -f if you want this)\n")); sl@0: sl@0: runTest(MemBaseline, _L("Processor baseline"), EFalse, EFalse, EFalse, 0); sl@0: runTest(MemFill, _L("Memory fill"), EFalse, EFalse, ETrue, 0); sl@0: runTest(MemCopy, _L("Memory copy"), ETrue, srcAlign, ETrue, 0); sl@0: runTest(MemSwap, _L("Memory swap"), ETrue, srcAlign, ETrue, 0); sl@0: } sl@0: break; sl@0: case ELengthTests: sl@0: test.Printf(_L("Running length benchmarks (may take a long time)\n")); sl@0: runTest(MemFill, _L("Fill length cached"), EFalse, EFalse, EFalse, 1); sl@0: runTest(MemFillUncached, _L("Fill length uncached"), EFalse, EFalse, EFalse, 1); sl@0: runTest(MemCopy, _L("Copy length cached"), EFalse, EFalse, EFalse, 1); sl@0: runTest(MemCopyUncached, _L("Copy length uncached"), EFalse, EFalse, EFalse, 1); sl@0: runTest(WordMove, _L("Word move length cached"), EFalse, EFalse, EFalse, 4); sl@0: runTest(WordMoveUncached,_L("Word move length uncached"), EFalse, EFalse, EFalse, 4); sl@0: break; sl@0: default: sl@0: test(EFalse); sl@0: break; sl@0: } sl@0: sl@0: test.End(); sl@0: return(KErrNone); sl@0: }