kerneltest/e32test/bench/t_membm.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:26:05 +0100
branchRCL_3
changeset 29 743008598095
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 1996-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:
// e32test\bench\t_membm.cpp
// 
//

#include <e32std.h>
#include <e32std_private.h>
#include <e32base.h>
#include <e32base_private.h>
#include <e32test.h>
#include <e32svr.h>

#define ALIGN_UP(x, y) (TInt8*)(_ALIGN_UP((TInt)(x), (y)))
#define ALIGN_DOWN(x, y) (TInt8*)(_ALIGN_DOWN((TInt)(x), (y)))

const TInt KHeapSize=720*1024;
const TInt KAverageOverInMilliseconds=500;
const TInt Len64K = 64*1024;

volatile TInt count;
volatile TInt iters;

TInt8* trg;
TInt8* src;
TInt8* dummy;
TInt8 trgoffset;
TInt8 srcoffset;
TInt len=64*1024;
TInt64 result;

RTest test(_L("T_MEMBM"));

GLREF_C TInt MemBaseline(TAny*);
GLREF_C TInt MemCopy(TAny*);
GLREF_C TInt MemMove(TAny*);
GLREF_C TInt MemFill(TAny*);
GLREF_C TInt MemSwap(TAny*);
GLREF_C TInt WordMove(TAny*);
GLREF_C TInt MemCopyUncached(TAny*);
GLREF_C TInt WordMoveUncached(TAny*);
GLREF_C TInt MemFillUncached(TAny*);
GLREF_C TInt PurgeCache();

TInt nextLen(TInt aTestLength)
	{
	if (len == Len64K)
		return 0;
	if (!aTestLength)
		return Len64K;

	TInt inc = aTestLength;
	for (TInt i = len >> 5 ; i ; i >>= 1)
		inc <<= 1;

	return len + inc;
	}

/**
 * Run benchmarks on the supplied function.
 *
 * @param aFunction			The function to benchmark
 * @param aTestBackwards	Run copy tests with overlapping areas to test backwards copy
 * @param aTestSrcAlign		Run tests for source alignments 0 - 31
 * @param aTestDestAlign	Run tests for destination alignments 0 - 31
 * @param aTestLength		If non-zero, run tests for different lengths starting at aTestLength
 */
TInt64 runTest(TThreadFunction aFunction,const TDesC& aTitle, TBool aTestBackwards, TBool aTestSrcAlign, TBool aTestDestAlign, TInt aTestLength)
    {
	TInt8* buffer = (TInt8*)User::Alloc(640 * 1024 + 32);
	test(buffer != 0);

	test(!(aTestLength && aTestBackwards)); // not supported
	
	TBool goingforward=ETrue;

	FOREVER
		{
		if (aTestLength)
			test.Printf(_L("Running length experiment on %S.  Results follow:\n"), &aTitle);
		
		len = 0;
		while(len = nextLen(aTestLength), len)
			{
			src = ALIGN_UP(buffer, 32);
			if (goingforward)
				trg = src + 512 * 1024;					// blow half a meg
			else
				trg = ALIGN_DOWN(src + len - 1, 32);	// ensure overlapping, doesn't work for length < 32

			if (aTestLength)
				test.Printf(_L("%d, "), len);
			else
				test.Printf(_L("Test array bases trg=0x%08x, src=0x%08x.  Running experiment on %S.  Results follow:\n"), trg, src, &aTitle);
			
			const TInt xsquare = aTestDestAlign ? 32 : 1;
			const TInt ysquare = aTestSrcAlign ? 32 : 1;

			for (srcoffset = 0 ; srcoffset < ysquare ; srcoffset++)
				{
				for (trgoffset = 0 ; trgoffset < xsquare ; trgoffset++)
					{
					RThread thread;
					TInt r=thread.Create(aTitle,aFunction,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
					if(r!=KErrNone)
						{
						test.Printf(_L("Failed to create thread with error %d\n"),r);
						return(r);
						}
					thread.SetPriority(EPriorityLess);
					thread.Resume();
					User::After(50000);  // 50 msec is more than enough in EKA2
					count=0;
					User::After(5000);   // even if the second reset fails, max inaccuracy is 5000 usecs
					count=0;			 // try and reduce the probability of failing to reset
					User::After(KAverageOverInMilliseconds*1000);
					result=count;
					thread.Kill(0);
					CLOSE_AND_WAIT(thread);
					PurgeCache();

					result *= 1000;
					result /= KAverageOverInMilliseconds;

					TInt s = I64INT(result);
					test.Printf(_L("%d, "),s);
					}
				test.Printf(_L("\n"));
				}
			}

		if (aTestBackwards && goingforward)
			goingforward = EFalse;
		else
			break;
		}
	
	User::Free(buffer);

	return(result);
    }

enum TTestType
	{
	ENormalTests,
	EFullTests,
	ELengthTests,
	};

// Return whether we should run the full alignment benchmarks
TTestType ParseCommandLine()
	{
	TBuf<32> args;
	User::CommandLine(args);
	
	if (args == _L("-f"))
		return EFullTests;
	else if (args == _L("-l"))
		return ELengthTests;
	else if (args != KNullDesC)
		{
		test.Printf(_L("usage: t_membm [OPTIONS]\n"));
		test.Printf(_L("  -f  Run full alignment benchmarks\n"));
		test.Printf(_L("  -l  Run memcpy length benchmarks\n"));
		test(EFalse);
		}
	
	return ENormalTests;
	}

TInt E32Main()
//
// Benchmark for Mem functions
//
    {

    test.Title();
    test.Start(_L("Benchmarks for Mem functions"));

	TTestType testType = ParseCommandLine();

	switch (testType)
		{
		case ENormalTests:
		case EFullTests:
			{
			TBool srcAlign = testType == EFullTests;
			
			if (srcAlign)
				test.Printf(_L("Running full alignment benchmarks (may take a long time)\n"));
			else
				test.Printf(_L("Not testing source alignment (run with -f if you want this)\n"));
			
			runTest(MemBaseline,     _L("Processor baseline"),   EFalse, EFalse,   EFalse, 0);
			runTest(MemFill,	     _L("Memory fill"),		     EFalse, EFalse,   ETrue,  0);
			runTest(MemCopy,	     _L("Memory copy"),		     ETrue,  srcAlign, ETrue,  0);
			runTest(MemSwap,	     _L("Memory swap"),		     ETrue,  srcAlign, ETrue,  0);
			}
			break;
		case ELengthTests:
			test.Printf(_L("Running length benchmarks (may take a long time)\n"));
			runTest(MemFill,         _L("Fill length cached"),        EFalse,  EFalse,  EFalse, 1);
			runTest(MemFillUncached, _L("Fill length uncached"),      EFalse,  EFalse,  EFalse, 1);
			runTest(MemCopy,         _L("Copy length cached"),        EFalse,  EFalse,  EFalse, 1);
			runTest(MemCopyUncached, _L("Copy length uncached"),      EFalse,  EFalse,  EFalse, 1);
			runTest(WordMove,        _L("Word move length cached"),   EFalse,  EFalse,  EFalse, 4);
			runTest(WordMoveUncached,_L("Word move length uncached"), EFalse,  EFalse,  EFalse, 4);
			break;
		default:
			test(EFalse);
			break;
		}

    test.End();
	return(KErrNone);
    }