Пример #1
0
// CheckStatsTotal
//------------------------------------------------------------------------------
void FBuildTest::CheckStatsTotal( const FBuildStats & stats, size_t numSeen, size_t numBuilt ) const
{
	size_t actualNumSeen = stats.GetNodesProcessed();
	TEST_ASSERT( actualNumSeen == numSeen );

	size_t actualNumBuilt = stats.GetNodesBuilt();
	TEST_ASSERT( actualNumBuilt == numBuilt );
}
Пример #2
0
// Generate
//------------------------------------------------------------------------------
void Report::Generate( const FBuildStats & stats )
{
	Timer t;

	// pre-allocate a large string for output
	m_Output.SetReserved( MEGABYTE );
	m_Output.SetLength( 0 );

	// generate some common data used in reporting
	GetLibraryStats( stats );

	// build the report
	CreateHeader();

	CreateTitle();

	CreateOverview( stats );

	DoCPUTimeByType( stats );
	DoCacheStats( stats );
	DoCPUTimeByLibrary();
	DoCPUTimeByItem( stats );

	DoIncludes();

	CreateFooter();

	// patch in time take
	const float time = t.GetElapsed();
	AStackString<> timeTakenBuffer;
	stats.FormatTime( time, timeTakenBuffer );
	char * placeholder = m_Output.Find( "^^^^    " );
	memcpy( placeholder, timeTakenBuffer.Get(), timeTakenBuffer.GetLength() );
	
}
Пример #3
0
// CheckStatsNode
//------------------------------------------------------------------------------
void FBuildTest::CheckStatsNode( const FBuildStats & stats, size_t numSeen, size_t numBuilt, Node::Type nodeType ) const
{
	const FBuildStats::Stats & nodeStats = stats.GetStatsFor( nodeType );

	size_t actualNumSeen = nodeStats.m_NumProcessed;
	TEST_ASSERT( actualNumSeen == numSeen );

	size_t actualNumBuilt = nodeStats.m_NumBuilt;
	TEST_ASSERT( actualNumBuilt == numBuilt );
}
// TestPCH
//------------------------------------------------------------------------------
void TestPrecompiledHeaders::TestPCH() const
{
	FBuildOptions options;
	options.m_ForceCleanBuild = true;
	options.m_UseCacheWrite = true;
	options.m_ShowSummary = true; // required to generate stats for node count checks

	#if defined( __WINDOWS__ )
		AStackString<> obj( "../../../../ftmp/Test/PrecompiledHeaders/PCHUser.obj" );
	#else
		AStackString<> obj( "../../../../ftmp/Test/PrecompiledHeaders/PCHUser.o" );
	#endif
	AStackString<> pch( "../../../../ftmp/Test/PrecompiledHeaders/PrecompiledHeader.pch" );
	AStackString<> lib( "../../../../ftmp/Test/PrecompiledHeaders/TestPCH.lib" );
	EnsureFileDoesNotExist( obj );
	EnsureFileDoesNotExist( pch );
	EnsureFileDoesNotExist( lib );

	FBuildStats stats = Build( options, false ); // don't use DB

	EnsureFileExists( obj );
	EnsureFileExists( pch );
	EnsureFileExists( lib );

	// Check stats
	//						Seen,	Built,	Type
	CheckStatsNode ( stats,	3,		2,		Node::FILE_NODE );	// cpp + pch 
	CheckStatsNode ( stats,	1,		1,		Node::COMPILER_NODE );
	CheckStatsNode ( stats,	2,		2,		Node::OBJECT_NODE );// obj + pch obj
	CheckStatsNode ( stats,	1,		1,		Node::LIBRARY_NODE );
	CheckStatsNode ( stats,	1,		1,		Node::DIRECTORY_LIST_NODE );
	CheckStatsNode ( stats,	1,		1,		Node::ALIAS_NODE );
	CheckStatsNode ( stats,	1,		1,		Node::DLL_NODE );
	CheckStatsTotal( stats,	10,		9 );

	// check we wrote all objects to the cache
	TEST_ASSERT( stats.GetStatsFor( Node::OBJECT_NODE ).m_NumCacheStores == 1 ); // only the main obj can be cached
}
Пример #5
0
// Test
//------------------------------------------------------------------------------
void TestCLR::Test() const
{
	FBuildOptions options;
	options.m_ForceCleanBuild = true;
	options.m_UseCacheWrite = true;
	options.m_ShowSummary = true; // required to generate stats for node count checks

	EnsureFileDoesNotExist( "../../../../ftmp/Test/CLR/clr.lib" );

	FBuildStats stats = Build( options, false, "CLR-Target" ); // dont' use DB

	EnsureFileExists( "../../../../ftmp/Test/CLR/clr.lib" );

	// Check stats
	//				 Seen,	Built,	Type
	CheckStatsNode ( stats,	3,		1,		Node::FILE_NODE );	// cpp
	CheckStatsNode ( stats,	1,		1,		Node::COMPILER_NODE );
	CheckStatsNode ( stats,	1,		1,		Node::OBJECT_NODE );
	CheckStatsNode ( stats,	1,		1,		Node::LIBRARY_NODE );
	CheckStatsNode ( stats,	1,		1,		Node::ALIAS_NODE );
	CheckStatsTotal( stats,	7,		5 );

	TEST_ASSERT( stats.GetCacheStores() == 0 ); // cache not supported due to compiler bug
}
Пример #6
0
// DoCPUTimeByItem
//------------------------------------------------------------------------------
void Report::DoCPUTimeByItem( const FBuildStats & stats )
{
	DoSectionTitle( "CPU Time by Item", "cpuTimeByItem" );

	DoTableStart();

	// Headings
	Write( "<tr><th style=\"width:100px;\">Time</th><th style=\"width:100px;\">Type</th><th>Name</th></tr>\n" );

	size_t numOutput = 0;

	// Result
	const Array< const Node * > & nodes = stats.GetNodesByTime();
	for ( const Node ** it = nodes.Begin();
		  it != nodes.End();
		  ++ it )
	{
		const Node * node = *it;
		float time = ( (float)node->GetProcessingTime() * 0.001f ); // ms to s
		const char * type = node->GetTypeName();
		const char * name = node->GetName().Get();

		// start collapsable section
		if ( numOutput == 10 )
		{
			DoToggleSection( (uint32_t)nodes.GetSize() - 10 );
		}

		Write( ( numOutput == 10 ) ? "<tr></tr><tr><td style=\"width:100px;\">%2.3fs</td><td style=\"width:100px;\">%s</td><td>%s</td></tr>\n"
								   : "<tr><td>%2.3fs</td><td>%s</td><td>%s</td></tr>\n", time, type, name );
		numOutput++;
	}

	DoTableStop();

	if ( numOutput > 10 )
	{
		Write( "</details>\n" );
	}
}
Пример #7
0
// GetLibraryStats
//------------------------------------------------------------------------------
void Report::GetLibraryStats(  const FBuildStats & stats )
{
	// gather library stats, sorted by CPU cost
	GetLibraryStatsRecurse( m_LibraryStats, stats.GetRootNode(), nullptr );
	m_LibraryStats.SortDeref();
}
Пример #8
0
// DoCPUTimeByType
//------------------------------------------------------------------------------
void Report::DoCPUTimeByType( const FBuildStats & stats )
{
	DoSectionTitle( "CPU Time by Node Type", "cpuTimeByNodeType" );

	// Summary Pie Chart
	Array< PieItem > items( 32, true );
	 
	for ( size_t i=0; i < (size_t)Node::NUM_NODE_TYPES; ++i )
	{
		const FBuildStats::Stats & nodeStats = stats.GetStatsFor( (Node::Type)i );
		if ( nodeStats.m_NumProcessed == 0 )
		{
			continue;
		}

		// label
		const char * typeName = Node::GetTypeName( Node::Type( i ) );
		const float value = (float)( (double)nodeStats.m_ProcessingTimeMS / (double)1000 );
		const uint32_t color = g_ReportNodeColors[ i ];

		PieItem item( typeName, value, color, (void *)i );
		items.Append( item );
	}

	items.Sort();

	// pie chart
	DoPieChart( items, " s" );

	// table
	DoTableStart();
	Write( "<tr><th width=80>Type</th><th width=80>Time</th><th width=80>Processed</th><th width=80>Built</th><th width=80>Cache Hits</th></tr>\n" );
	for ( size_t i=0; i < items.GetSize(); ++i )
	{
		Node::Type type = (Node::Type)(size_t)items[ i ].userData;
		const FBuildStats::Stats & nodeStats = stats.GetStatsFor( type );
		if ( nodeStats.m_NumProcessed == 0 )
		{
			continue;
		}

		const char * typeName = Node::GetTypeName( type );
		const float value = (float)( (double)nodeStats.m_ProcessingTimeMS / (double)1000 );
		const uint32_t processed = nodeStats.m_NumProcessed;
		const uint32_t built = nodeStats.m_NumBuilt;
		const uint32_t cacheHits = nodeStats.m_NumCacheHits;

		Write( "<tr><td>%s</td><td>%2.3fs</td><td>%u</td><td>%u</td>", 
					typeName, 
					value, 
					processed, 
					built, 
					cacheHits );
		if ( type == Node::OBJECT_NODE )
		{
			// cacheable
			Write( "<td>%u</td></tr>\n", cacheHits );
		}
		else
		{
			// non-cacheable
			Write( "<td>-</td></tr>\n" );
		}
	}
	DoTableStop();
}
Пример #9
0
// CreateOverview
//------------------------------------------------------------------------------
void Report::CreateOverview( const FBuildStats & stats )
{
	DoSectionTitle( "Overview", "overview" );

	AStackString<> buffer;

	DoTableStart();

	// Headings
	Write( "<tr><th width=150>Item</th><th>Details</th></tr>\n" );

	// Full command line
    AStackString<> commandLineBuffer;
    Env::GetCmdLine( commandLineBuffer );
    #if defined( __WINDOWS__ )
        const char * exeExtension = strstr( commandLineBuffer.Get(), ".exe\"" );
        const char * commandLine = exeExtension ? ( exeExtension + 5 ) : commandLineBuffer.Get(); // skip .exe + closing quote
    #else
        const char * commandLine = commandLineBuffer.Get();
    #endif
	Write( "<tr><td width=80>Cmd Line Options</td><td>%s</td></tr>", commandLine );

	// Target
	AStackString<> targets;
	const Node * rootNode = stats.GetRootNode();
	if (rootNode->GetType() != Node::PROXY_NODE)
	{
		targets = rootNode->GetName();
	}
	else
	{
		const Dependencies & childNodes = rootNode->GetStaticDependencies();
		size_t num = childNodes.GetSize();
		for ( size_t i=0; i<num; ++i )
		{
			if ( i != 0 )
			{
				targets += ", ";
			}
			const Node * child = childNodes[ i ].GetNode();
			targets += child->GetName();
		}
	}
	Write( "<tr><td>Target(s)</td><td>%s</td></tr>\n", targets.Get() );

	// Result
	const bool buildOK = ( stats.GetRootNode()->GetState() == Node::UP_TO_DATE );
	Write( "<tr><td>Result</td><td>%s</td></tr>\n", buildOK ? "OK" : "FAILED" );

	// Real Time
	float totalBuildTime = stats.m_TotalBuildTime;
	stats.FormatTime( totalBuildTime, buffer );
	Write( "<tr><td>Time</td><td>%s</td></tr>\n", buffer.Get() );

	// Local CPU Time 
	float totalLocalCPUInSeconds = (float)( (double)stats.m_TotalLocalCPUTimeMS / (double)1000 );
	stats.FormatTime( totalLocalCPUInSeconds, buffer );
	float localRatio = ( totalLocalCPUInSeconds / totalBuildTime );
	Write( "<tr><td>CPU Time</td><td>%s (%2.1f:1)</td></tr>\n", buffer.Get(), localRatio );

	// version info
	Write( "<tr><td>Version</td><td>%s %s</td></tr>\n", FBUILD_VERSION_STRING, FBUILD_VERSION_PLATFORM );

	// report time
	char timeBuffer[ 256 ];
	#if defined( __WINDOWS__ )
		VERIFY( ::GetTimeFormat( LOCALE_NAME_USER_DEFAULT,		// LCID Locale
								 TIME_FORCE24HOURFORMAT,		// DWORD dwFlags
								 nullptr,						// SYSTEMTIME *lpTime
								 nullptr,						// LPCTSTR lpFormat,
								 timeBuffer,					// LPTSTR lpTimeStr,
								 256 ) );						// int cchTime
	#elif defined( __APPLE__ )
		timeBuffer[ 0 ] = '\000'; // TODO:MAC Implement GetTimeFormat in Report
	#elif defined( __LINUX__ )
		timeBuffer[ 0 ] = '\000'; // TODO:LINUX Implement GetTimeFormat in Report
	#else
		#error Unknown platform
	#endif

	char dateBuffer[ 256 ];
	#if defined( __WINDOWS__ )
		VERIFY( ::GetDateFormat( LOCALE_NAME_USER_DEFAULT,		// LCID Locale
								 DATE_LONGDATE,					// DWORD dwFlags
								 nullptr,						// SYSTEMTIME *lpTime
								 nullptr,						// LPCTSTR lpFormat,
								 dateBuffer,					// LPTSTR lpTimeStr,
								 256 ) );						// int cchTime
	#elif defined( __APPLE__ )
		dateBuffer[ 0 ] = '\000'; // TODO:MAC Implement GetDateFormat in Report
	#elif defined( __LINUX__ )
		dateBuffer[ 0 ] = '\000'; // TODO:LINUX Implement GetDateFormat in Report
	#else
		#error Unknown platform
	#endif

	// NOTE: leave space to patch in time taken later "^^^^                          "
	Write( "<tr><td>Report Generated</td><td>^^^^                         - %s %s</td></tr>\n", dateBuffer, timeBuffer );

	DoTableStop();
}