kerneltest/e32test/benchmark/bm_suite.h
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:26:05 +0100
branchRCL_3
changeset 29 743008598095
parent 0 a41df078684a
child 39 2bb754abd467
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) 2002-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:
//

#if !defined(__BM_SUITE_H__)
#define __BM_SUITE_H__

#include <e32test.h>

#include "d32bm.h"

/**
 * Gets access to the benchmark suite global log window/file.
 */
extern RTest test;
/**
 * Tests for an error condition.
 *
 * If the error condition is detected the macro prints out the file name, the line number and 
 * the error code, and aborts the benchmark suite.  
 *
 * @param aError an error number; printed out in the case if the error condition is detected.
 * @param aCond non-error condition: if 1 - no errors; if 0 - error. 
 */
#define BM_ERROR(aError, aCond) \
	__ASSERT_ALWAYS(aCond, bm_error_detected((TInt) aError, "'"#aCond"'", __FILE__, __LINE__))
void bm_error_detected(TInt aError, char* aCond, char* aFile, TInt aLine);

/**
 * Verify a condition
 *
 * If the value of condition is 0 prints out the file name, the line number and 
 * aborts the benchmark suite.
 *
 * @param aCond the condition that shell be verified.
 */

#define BM_ASSERT(aCond) \
	__ASSERT_DEBUG(aCond, bm_assert_failed("'"#aCond"'", __FILE__, __LINE__))
void bm_assert_failed(char* aFile, char* aCond, TInt aLine);

/**
 * An object of <code>TBMResult</code> class collects results of a measurement of a single perfrormance characteristic.
 * 
 * Objects of <code>TBMResult</code> class are typically reside in benchmark programs' static data
 * and returned as programs' results.
 */
class TBMResult
	{
public:
	/**
	 * Constructs a non-initialized <code>TBMResult</code> object. 
	 * Such a non-intialised object must be reset using void <code>TBMResult::Reset(const TDesC&)</code> function 
	 * prior to be actually used.
	 */
	TBMResult()	{}
	/**
	 * Constructs a <code>TBMResult</code> object. 
	 *
	 * @param aName the measurement tite.
	 */
	TBMResult(const TDesC& aName); 
	/**
	 * Resets an existing <code>TBMResult</code> object. 
	 * Sets the object in exactly the same state as <code>TBMResult::TBMResult(const TDesC&)</code>.
	 *
	 * @param aName the measurement tite.
	 */ 
	void Reset(const TDesC& aName);
	/**
	 * Stores the result of a new iteration.
	 *
	 * @param aTicks the iteration's elapsed time in ticks.
	 */
	void Cumulate(TBMTicks aTicks);
	/**
	 * Stores the cumulated result of a number of iterations.
	 *
	 * @param aTicks the cumulated elapsed time
	 * @param aIter the number of iterations.
	 */
	void Cumulate(TBMTicks aTicks, TBMUInt64 aIter);
	/**
	 * Calculate <code>TBMResult::iMin, TBMResult::iMax, TBMResult::iAverage</code> in nano-seconds
	 */
	void Update();
	/**
	 * The title of the performance measurement
	 */
	TPtrC	iName;
	/**
	 * The number of iteration has been performed
	 */
	TBMUInt64	iIterations;
	/**
	 * The minimal elapsed time in nano-seconds.
	 */
	TBMNs	iMin;
	/**
	 * The maximal elapsed time in nano-seconds
	 */ 
	TBMNs	iMax;
	/**
	 * The average elapsed time in nano-seconds.
	 */
	TBMNs	iAverage;

	enum
		{ 	
		/**
		 * The size of the buffer for the results of leading iterations
		 */
		KHeadSize = 4
		};
	enum
		{
		/**
		 * The size of the buffer for the results of tailing iterations
		 */
		KTailSize = 4 
		};
	/**
	 * The buffer with the results of <code>KHeadSize</code> leading iterations.
	 */
	TBMNs	iHead[KHeadSize];
	/**
	 * The buffer with the results of <code>KTailSize</code> trailing iterations.
	 */
	TBMNs	iTail[KTailSize];

// private:

	void Reset();
	
	TBMTicks	iMinTicks;				// the minimal elapsed time in ticks
	TBMTicks	iMaxTicks;				// the maximal elapsed time in ticks
	TBMTicks	iCumulatedTicks;		// the elapsed time in ticks cumulated over iCumulatedIterations
	TBMUInt64	iCumulatedIterations;	// the number of iterations for iCumulatedTicks

	TBMTicks	iHeadTicks[KHeadSize];	// the first KHeadSize results in ticks
	TBMTicks	iTailTicks[KTailSize];	// the last KTailSize results in ticks
	};

/**
 * An object of <code>TBMTimeInterval</code> can be used to measure potentially very long time interval.
 * 
 * If the measured time interval is shorter than the period of <code>RBMTimer</code> 
 * this high-precision timer will be used; otherwise, <code>TTime</code> timer will be used.
 */
class TBMTimeInterval
	{
public:
	/**
	 * A static function to initialize the class static state. 
	 * Called once by the benchmark suite launcher.
	 */
	static void Init();
	/**
	 * Begins the time interval measurement.
	 */
	void Begin();
	/**
	 * Ends the time interval measurement.
	 *
	 * @return the elapsed time in nano-seconds
	 */
	TBMNs EndNs();
	/**
	 * Ends the time interval measurement.
	 *
	 * @return the elapsed time in <code>RBMTimer</code> ticks. 
	 *		Note that the time is always returned in <code>RBMTimer</code> ticks regardless which of two timers,
	 *		<code>TTime</code> or <code>RBMTimer</code>, was actually used.
	 */
	TBMTicks End();

	/**
	 * Period of RBMTimer in nano-seconds
	 */
	static TBMNs	iStampPeriodNs;
	/**
	 * Period of RBMTimer in ticks
	 */
	static TBMTicks	iStampPeriod;

private:

	TBMTicks	iStamp;				// the starting time in RBMTimer ticks
	TTime		iTime;				// the starting TTime
	};


/**
 * Calculates elapsed time in ticks taking care about possible timer overflow.
 *
 * @param aT0 the beginning of the measured interval
 * @param aT1 the end of the measured interval.
 * 
 */
inline TBMTicks TBMTicksDelta(TBMTicks aT0, TBMTicks aT1)
	{
	return (aT0 <= aT1) ? (aT1 - aT0) : TBMTimeInterval::iStampPeriod - (aT0 - aT1);
	}


/**
 * Absolute thread prioiries to be used by benchmark programs
 */
enum 
	{
	/**
	 * Absolute priority to be used for high-priority threads.
	 * 
	 */
	KBMPriorityHigh = 60, // 60 is above all DFC 26 is below timer DFC
	/**
	 * Absolute priority to be used for middle-priority threads.
	 * This is also the default prioirty - performance benchmarks are started at this prioirty.
	 */	
	KBMPriorityMid = KBMPriorityHigh - 1,
	/**
	 * Absolute priority to be used for low-priority threads.
	 */
	KBMPriorityLow = KBMPriorityMid - 1
	};


/**
 * An object of <code>TBMSpawnArgs</code> type is used to pass arguments through 
 * <code>BMProgram::SpawnChild()</code> function from a parent to a child thread.
 *
 * <code>TBMSpawnArgs</code> is typically used as the base class for the actual argument passing object 
 * which may define some additional benchmark program specific arguments. 
 * The command line descriptor is used to pass a copy of the whole <code>TBMSpawnArgs</code> object 
 * from the parent process to the child one.
 */
struct TBMSpawnArgs
	{
	/**
	 * A magic value to allow the child recognize a command line as a <code>TBMSpawnArgs</code> object.
	 * Intialized by constructor.
	 */
	TInt			iMagic;
	/**
	 * A handle to the parent thread. 
	 * Intialized by constructor.
	 */
	RThread			iParent;
	/**
	 * The id of the parent thread.
	 * Intialized by constructor.
	 */
	TThreadId		iParentId;
	/**
	 * If <code>ETrue</code> the child thread runs in a separate process; 
	 * otherwise, the child thread runs within the parent's process.
	 * Intialized by constructor.
	 */
	TBool			iRemote;
	/**
	 * The child entry point.
	 * Intialized by constructor.
	 */
	TThreadFunction iChildFunc;
	/**
	 * The child thread absolute prioirty.
	 * Intialized by constructor.
	 */
	TInt			iChildPrio;

	TInt			iChildOrigPriority;
	/**
	 * The actual size of the <code>TBMSpawnArgs</code> object.
	 * Intialized by constructor.
	 */
	TInt			iSize;
	/**
	 * The TBMSpawnArgs magic value.
	 */
	static const TInt KMagic;
	/**
	 * Construct a new <code>TBMSpawnArgs</code> object.
	 *
	 * @param aChildFunc the child entry point
	 * @param aChildPrio the child thread absolute prioirty
	 * @param aRemote if <code>ETrue</code> the child thread must be created in a separate process; 
	 *		otherwise, the child thread must be created within the parent's process.
	 */
	TBMSpawnArgs(TThreadFunction aChildFunc, TInt aChildPrio, TBool aRemote, TInt aSize);
	/**
	 * Releases all allocated resources e.g. (<code>iParent</code> handle)
	 */
	~TBMSpawnArgs();
	};

/**
 * Child thread interface. Returned by <code>BMProgram::SpawnChild()</code>
 */
class MBMChild
	{
public:
	/**
	 * Wait for the actual child thread termination.
	 */
	virtual void WaitChildExit() = 0;
	/**
	 * Requests the child thread termination.
	 */
	virtual void Kill() = 0;
	};

/**
 * A benchmark program is implemented as a sub-class of the abstract <code>BMProgram</code> class.
 * 
 * A typical benchmark program implements <code>BMProgram::Run()</code> pure virtual function and 
 * instantiate an object of the implemented sub-class in its static data.
 */
class BMProgram 
	{
private:

	BMProgram*	iNext;
	TPtrC		iName;

	MBMChild* SpawnLocalChild(TBMSpawnArgs*);
	MBMChild* SpawnRemoteChild(TBMSpawnArgs*);
	
public:

	/**
	 * Utility function to change a thread's absolute priority.
	 * 
	 * @param aThread a handle ro the target thread.
	 * @param aNewPrio a new absolute priority for the target thread
	 * @return the old absolute prioirty of the target thread 
	 */
	static TInt SetAbsPriority(RThread aThread, TInt aNewPrio);	
	
	/**
	 * Constructs a new <code>BMProgram</code> object.
	 *
	 * @param aName the bechmark program's title
	 */
	BMProgram(const TDesC& aName) : iName(aName)
		{}

	/**
	 * Gets the nest program in the banchmark suite
	 *
	 * @return a pointer to the <code>BMProgram</code> object corresponding to the next benchmark program
	 *		in the benchmark suite
	 */
	BMProgram*& Next()
		{
		return iNext;
		}
	/**
	 * Gets the benchmark program title
	 * 
	 * @return a refernce to the descriptor containing the benchmark program title.
	 */
	const TDesC& Name()
		{
		return iName;
		}
	/**
	 * Runs the benchmark program.
	 *
	 * @param aIter the required number of iterations
	 * @retval aCount the number of performance characteristics measured by the benchmark program.
	 * @return a pointer to an array of <code>TBMResult</code> objects with the results of measurements of
	 *		individual performance characteristics. The number of array's elements is returned as 
	 *		aCount argument.
	 */
	virtual TBMResult* Run(TBMUInt64 aIter, TInt* aCount) = 0;

	/**
	 * Spawn a child thread
	 * 
	 * @param args a pointer to a <code>TBMSpawnArgs</code> object that contains genric spawn operation parameters
	 *		as well as program specific arguments to be passed to the chile thread.
	 */
	MBMChild* SpawnChild(TBMSpawnArgs* args);

	/**
	 * The main benchmark thread's absolute priority as was assigned by the loader. 
	 */
	TInt	iOrigAbsPriority;
	};

/**
 * The benchmark suite wide handle to the high-precision <code>RBMTimer</code>.
 */
extern RBMTimer bmTimer;
extern BMProgram* bmSuite;

void AddrtLatency();
void AddOverhead();
void AddSync();
void AddIpc();
void AddThread();
void AddProperty();


#endif