mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-04 18:09:53 +03:00
1
This commit is contained in:
673
gcsdk/messagelist.cpp
Normal file
673
gcsdk/messagelist.cpp
Normal file
@@ -0,0 +1,673 @@
|
||||
//====== Copyright , Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose: Provides names for GC message types
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
namespace GCSDK
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: allow global initializers for a list of message infos. The message
|
||||
// list will assemble them all into a single list when it initializes.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CMessageListRegistration
|
||||
{
|
||||
public:
|
||||
CMessageListRegistration( MsgInfo_t *pMsgInfo, int cMsgInfo, void *pExtra = NULL );
|
||||
|
||||
static CMessageListRegistration *sm_pFirst;
|
||||
CMessageListRegistration *m_pNext;
|
||||
MsgInfo_t *m_pMsgInfo;
|
||||
int m_cMsgInfo;
|
||||
};
|
||||
|
||||
|
||||
DECLARE_GC_EMIT_GROUP( g_EGMessages, messages );
|
||||
|
||||
//function called when a message is tallied but not registered properly. Used to help consolidate behavior for untracked messages
|
||||
static void HandleUntrackedMsg( const char* pszMsgOperation, uint32 nMsgID )
|
||||
{
|
||||
//for now output this as verbose so that we can clean up the initial spam. Then promote this to warnings in the future
|
||||
EG_VERBOSE( g_EGMessages, "Found %s message with ID %d that was not properly registered. Unable to tally information\n", pszMsgOperation, nMsgID );
|
||||
}
|
||||
|
||||
|
||||
CMessageListRegistration::CMessageListRegistration( MsgInfo_t *pMsgInfo, int cMsgInfo, void *pExtra )
|
||||
: m_pMsgInfo( pMsgInfo ),
|
||||
m_cMsgInfo( cMsgInfo )
|
||||
{
|
||||
m_pNext = sm_pFirst;
|
||||
sm_pFirst = this;
|
||||
}
|
||||
|
||||
CMessageListRegistration *CMessageListRegistration::sm_pFirst = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns the name of a message type
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *PchMsgNameFromEMsg( MsgType_t eMsg )
|
||||
{
|
||||
const char *pchMsgName = k_rgchUnknown;
|
||||
g_theMessageList.GetMessage( eMsg, &pchMsgName, MT_GC );
|
||||
return pchMsgName;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void MsgRegistrationFromEnumDescriptor( const ::google::protobuf::EnumDescriptor *pEnumDescriptor, int nTypeMask )
|
||||
{
|
||||
// build the struct list for messages
|
||||
MsgInfo_t *pMsgInfos = new MsgInfo_t[ pEnumDescriptor->value_count() ];
|
||||
memset( pMsgInfos, 0, sizeof( MsgInfo_t ) * pEnumDescriptor->value_count() );
|
||||
|
||||
for ( int i = 0; i < pEnumDescriptor->value_count(); ++i )
|
||||
{
|
||||
const ::google::protobuf::EnumValueDescriptor *pEnumValueDescriptor = pEnumDescriptor->value(i);
|
||||
pMsgInfos[ i ].eMsg = pEnumValueDescriptor->number();
|
||||
pMsgInfos[ i ].pchMsgName = pEnumValueDescriptor->name().c_str();
|
||||
pMsgInfos[ i ].nFlags = nTypeMask;
|
||||
}
|
||||
|
||||
new CMessageListRegistration( pMsgInfos, pEnumDescriptor->value_count() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CMessageList g_theMessageList;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CMessageList
|
||||
//
|
||||
// builds a hash of the MsgInfo_t table so that information about messages
|
||||
// can be found without searching.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CMessageList::CMessageList( ) : m_bProfiling( false ), m_ulProfileMicrosecs( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CMessageList
|
||||
//
|
||||
// builds a hash of the MsgInfo_t table so that information about messages
|
||||
// can be found without searching.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMessageList::BInit( )
|
||||
{
|
||||
m_bProfiling = false;
|
||||
m_ulProfileMicrosecs = 0;
|
||||
|
||||
// figure out our message count
|
||||
int cMessageInfos = 0;
|
||||
for( CMessageListRegistration *pReg = CMessageListRegistration::sm_pFirst; pReg != NULL; pReg = pReg->m_pNext)
|
||||
{
|
||||
cMessageInfos += pReg->m_cMsgInfo;
|
||||
}
|
||||
|
||||
// message indexes should fit in a short
|
||||
Assert( cMessageInfos < SHRT_MAX );
|
||||
|
||||
m_vecMsgInfo.EnsureCapacity( cMessageInfos );
|
||||
m_vecMsgInfo.RemoveAll();
|
||||
m_vecMessageInfoBuckets.RemoveAll();
|
||||
|
||||
int nIndex = 0;
|
||||
for( CMessageListRegistration *pReg = CMessageListRegistration::sm_pFirst; pReg != NULL; pReg = pReg->m_pNext)
|
||||
{
|
||||
for ( int nRegIndex = 0; nRegIndex < pReg->m_cMsgInfo; nRegIndex++ )
|
||||
{
|
||||
nIndex = m_vecMsgInfo.AddToTail( pReg->m_pMsgInfo[nRegIndex] );
|
||||
|
||||
int nSlot;
|
||||
int nBucket = HashMessage( pReg->m_pMsgInfo[nRegIndex].eMsg, nSlot );
|
||||
|
||||
AssureBucket( nBucket );
|
||||
|
||||
if ( m_vecMessageInfoBuckets[nBucket][nSlot] != -1 )
|
||||
{
|
||||
int otherIndex = m_vecMessageInfoBuckets[nBucket][nSlot];
|
||||
MsgInfo_t &otherMsg = m_vecMsgInfo[ otherIndex ];
|
||||
AssertFatalMsg2( false, "Message collision: %s redefined as %s",
|
||||
otherMsg.pchMsgName,
|
||||
pReg->m_pMsgInfo[nRegIndex].pchMsgName);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecMessageInfoBuckets[nBucket][nSlot] = (short) nIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//start our window
|
||||
ResetWindow();
|
||||
//and start our global timer
|
||||
m_sCollectTime[ MsgInfo_t::k_EStatsGroupGlobal ].SetToJobTime();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tally the sending of a message
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessageList::TallySendMessage( MsgType_t eMsgType, uint32 unMsgSize, uint32 nSourceMask )
|
||||
{
|
||||
short nIndex = GetMessageIndex( eMsgType );
|
||||
if ( nIndex == - 1 )
|
||||
{
|
||||
HandleUntrackedMsg( "send", eMsgType );
|
||||
return;
|
||||
}
|
||||
|
||||
TallyMessageInternal( m_vecMsgInfo[nIndex],MsgInfo_t::k_EStatsTypeSent, unMsgSize, nSourceMask );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tally the receiving of a message
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessageList::TallyReceiveMessage( MsgType_t eMsgType, uint32 unMsgSize, uint32 nSourceMask )
|
||||
{
|
||||
short nIndex = GetMessageIndex( eMsgType );
|
||||
if ( nIndex == - 1 )
|
||||
{
|
||||
HandleUntrackedMsg( "receive", eMsgType );
|
||||
return;
|
||||
}
|
||||
|
||||
TallyMessageInternal( m_vecMsgInfo[nIndex], MsgInfo_t::k_EStatsTypeReceived, unMsgSize, nSourceMask );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tally the receiving of a message
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessageList::TallyMultiplexedMessage( MsgType_t eMsgType, uint32 uSent, uint32 cRecipients, uint32 uMsgSize, uint32 nSourceMask )
|
||||
{
|
||||
short nIndex = GetMessageIndex( eMsgType );
|
||||
if ( nIndex == - 1 )
|
||||
{
|
||||
HandleUntrackedMsg( "multiplex", eMsgType );
|
||||
return;
|
||||
}
|
||||
|
||||
MsgInfo_t &msgInfo = m_vecMsgInfo[nIndex];
|
||||
TallyMessageInternal( msgInfo, MsgInfo_t::k_EStatsTypeMultiplexedSends, uSent, nSourceMask, 1 );
|
||||
TallyMessageInternal( msgInfo, MsgInfo_t::k_EStatsTypeMultiplexedSendsRaw, uMsgSize * cRecipients, nSourceMask, cRecipients );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tally the receiving of a message
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessageList::TallyMessageInternal( MsgInfo_t &msgInfo, MsgInfo_t::EStatsType eBucket, uint32 unMsgSize, uint32 nSourceMask, uint32 cMessages )
|
||||
{
|
||||
//log this for global stats
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupGlobal ][ eBucket ].nCount += cMessages;
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupGlobal ][ eBucket ].uBytes += unMsgSize;
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupGlobal ][ eBucket ].nSourceMask |= nSourceMask;
|
||||
|
||||
//track this in our current timing window
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupWindow ][ eBucket ].nCount += cMessages;
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupWindow ][ eBucket ].uBytes += unMsgSize;
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupWindow ][ eBucket ].nSourceMask |= nSourceMask;
|
||||
|
||||
//track our window totals as well
|
||||
m_WindowTotals[ eBucket ].nCount += cMessages;
|
||||
m_WindowTotals[ eBucket ].uBytes += unMsgSize;
|
||||
m_WindowTotals[ eBucket ].nSourceMask |= nSourceMask;
|
||||
|
||||
//and if we are profiling, track the data into our profiling window
|
||||
if ( m_bProfiling )
|
||||
{
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupProfile ][ eBucket ].nCount += cMessages;
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupProfile ][ eBucket ].uBytes += unMsgSize;
|
||||
msgInfo.stats[ MsgInfo_t::k_EStatsGroupProfile ][ eBucket ].nSourceMask |= nSourceMask;
|
||||
}
|
||||
}
|
||||
|
||||
//called to obtain the totals for the timing window
|
||||
const MsgInfo_t::Stats_t& CMessageList::GetWindowTotal( MsgInfo_t::EStatsType eType ) const
|
||||
{
|
||||
return m_WindowTotals[ eType ];
|
||||
}
|
||||
|
||||
//called to reset the window timings
|
||||
void CMessageList::ResetWindow()
|
||||
{
|
||||
//reset when our window started
|
||||
m_sCollectTime[ MsgInfo_t::k_EStatsGroupWindow ].SetToJobTime();
|
||||
|
||||
// starting a new window... clear everything
|
||||
FOR_EACH_VEC( m_vecMsgInfo, nIndex )
|
||||
{
|
||||
for( uint32 nType = 0; nType < MsgInfo_t::k_EStatsType_Count; nType++ )
|
||||
{
|
||||
m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupWindow ][ nType ].nCount = 0;
|
||||
m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupWindow ][ nType ].uBytes = 0;
|
||||
m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupWindow ][ nType ].nSourceMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//and clear our totals
|
||||
for( uint32 nType = 0; nType < MsgInfo_t::k_EStatsType_Count; nType++ )
|
||||
{
|
||||
m_WindowTotals[ nType ].nCount = 0;
|
||||
m_WindowTotals[ nType ].uBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Turns snapshot profiling on and off
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessageList::EnableProfiling( bool bEnableProfiling )
|
||||
{
|
||||
m_bProfiling = bEnableProfiling;
|
||||
if ( m_bProfiling )
|
||||
{
|
||||
m_sCollectTime[ MsgInfo_t::k_EStatsGroupProfile ].SetToJobTime();
|
||||
|
||||
// starting a new profile... clear everything
|
||||
FOR_EACH_VEC( m_vecMsgInfo, nIndex )
|
||||
{
|
||||
for( uint32 nType = 0; nType < MsgInfo_t::k_EStatsType_Count; nType++ )
|
||||
{
|
||||
m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupProfile ][ nType ].nCount = 0;
|
||||
m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupProfile ][ nType ].uBytes = 0;
|
||||
m_vecMsgInfo[ nIndex ].stats[ MsgInfo_t::k_EStatsGroupProfile ][ nType ].nSourceMask = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ulProfileMicrosecs = m_sCollectTime[ MsgInfo_t::k_EStatsGroupProfile ].CServerMicroSecsPassed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint64 CMessageList::GetGroupDuration( MsgInfo_t::EStatsGroup eGroup ) const
|
||||
{
|
||||
//handle the special case of it being a profile, where if we are no longer profiling, we want to use our cached value
|
||||
if( ( eGroup == MsgInfo_t::k_EStatsGroupProfile ) && !m_bProfiling )
|
||||
{
|
||||
return m_ulProfileMicrosecs;
|
||||
}
|
||||
|
||||
//otherwise we can just use the timer directly
|
||||
return m_sCollectTime[ eGroup ].CServerMicroSecsPassed();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// print statistics bout each message we handle
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessageList::PrintStats( bool bShowAll, bool bSortByFrequency, MsgInfo_t::EStatsGroup eGroup, MsgInfo_t::EStatsType eType, uint32 nSourceMask ) const
|
||||
{
|
||||
// Figure out which time value we should use for rate calcs
|
||||
uint64 ulMicroseconds = GetGroupDuration( eGroup );
|
||||
|
||||
// work out a sorted list
|
||||
CUtlMap<uint64, uint32> mapValueToMsg( DefLessFunc( uint64 ) );
|
||||
uint64 unTotalBytes = 0;
|
||||
uint32 unTotalMessages = 0;
|
||||
|
||||
FOR_EACH_VEC( m_vecMsgInfo, n )
|
||||
{
|
||||
//see if we are looking for a particular source, and if so, if this has that source set
|
||||
if( nSourceMask && ( ( m_vecMsgInfo[n].stats[ eGroup ][ eType ].nSourceMask & nSourceMask ) == 0 ) )
|
||||
continue;
|
||||
|
||||
uint32 nCount = m_vecMsgInfo[n].stats[ eGroup ][ eType ].nCount;
|
||||
uint64 uBytes = m_vecMsgInfo[n].stats[ eGroup ][ eType ].uBytes;
|
||||
|
||||
unTotalMessages += nCount;
|
||||
unTotalBytes += uBytes;
|
||||
|
||||
if ( nCount == 0 && !bShowAll )
|
||||
continue;
|
||||
|
||||
mapValueToMsg.Insert( bSortByFrequency ? (uint64)nCount : uBytes, n );
|
||||
}
|
||||
|
||||
double fSeconds = ulMicroseconds / ( 1000.0 * 1000.0 );
|
||||
|
||||
// 5, 46, 10, 6, 14, 6, 10, 10
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%s", "EMsg MessageName Count % Bytes % MsgPS Avg/Msg KBPS\n" );
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%s", "----- ---------------------------------------------- ---------- ------ -------------- ------ --------- ---------- ----------\n" );
|
||||
|
||||
for ( uint16 iValue = mapValueToMsg.LastInorder(); iValue != mapValueToMsg.InvalidIndex(); iValue = mapValueToMsg.PrevInorder( iValue ) )
|
||||
{
|
||||
uint32 n = mapValueToMsg[iValue];
|
||||
|
||||
//see if we are looking for a particular source, and if so, if this has that source set
|
||||
if( nSourceMask && ( ( m_vecMsgInfo[n].stats[ eGroup ][ eType ].nSourceMask & nSourceMask ) == 0 ) )
|
||||
continue;
|
||||
|
||||
uint32 nCount = m_vecMsgInfo[n].stats[ eGroup ][ eType].nCount;
|
||||
uint64 uBytes = m_vecMsgInfo[n].stats[ eGroup ][ eType].uBytes;
|
||||
|
||||
uint32 uAvgMsg = 0;
|
||||
if ( nCount > 0 )
|
||||
uAvgMsg = uBytes / nCount;
|
||||
|
||||
float flCountPerc = 0;
|
||||
if ( unTotalMessages > 0 )
|
||||
flCountPerc = nCount * 100.0f / unTotalMessages;
|
||||
float flBytesPerc = 0;
|
||||
if ( unTotalBytes > 0 )
|
||||
flBytesPerc = uBytes * 100.0f / unTotalBytes;
|
||||
double fMsgPS = 0.0;
|
||||
if ( ulMicroseconds > 0 )
|
||||
fMsgPS = nCount / fSeconds;
|
||||
double fKBPS = 0.0f;
|
||||
if ( ulMicroseconds > 0 )
|
||||
fKBPS = uBytes / ( fSeconds * 1000.0 );
|
||||
|
||||
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%5u %-46s %10u %5.1f%% %14llu %5.1f%% %9.1f %10u %10.2f\n",
|
||||
m_vecMsgInfo[n].eMsg,
|
||||
m_vecMsgInfo[n].pchMsgName,
|
||||
nCount,
|
||||
flCountPerc,
|
||||
uBytes,
|
||||
flBytesPerc,
|
||||
fMsgPS,
|
||||
uAvgMsg,
|
||||
fKBPS );
|
||||
}
|
||||
|
||||
uint32 uAvgMsgTotal = 0;
|
||||
if ( unTotalMessages > 0 )
|
||||
uAvgMsgTotal = unTotalBytes / unTotalMessages;
|
||||
double fMsgPS = 0.0;
|
||||
if ( ulMicroseconds > 0 )
|
||||
fMsgPS = unTotalMessages / fSeconds;
|
||||
double fKBPSTotal = 0.0;
|
||||
if ( ulMicroseconds > 0 )
|
||||
fKBPSTotal = unTotalBytes / ( fSeconds * 1000.0 );
|
||||
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "----- ---------------------------------------------- ---------- ------ -------------- ------ --------- ---------- ----------\n" );
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "Totals %10u 100.0%% %14llu 100.0%% %9.1f %10u %10.2f\n",
|
||||
unTotalMessages,
|
||||
unTotalBytes,
|
||||
fMsgPS,
|
||||
uAvgMsgTotal,
|
||||
fKBPSTotal );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// print statistics bout each message we handle
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessageList::PrintMultiplexStats( MsgInfo_t::EStatsGroup eGroup, bool bSortByFrequency, uint32 nSourceMask ) const
|
||||
{
|
||||
// Figure out which time value we should use for rate calcs
|
||||
uint64 ulMicroseconds = GetGroupDuration( eGroup );
|
||||
|
||||
MsgInfo_t::Stats_t rgTotals[MsgInfo_t::k_EStatsType_Count];
|
||||
|
||||
const MsgInfo_t::EStatsType eMultiType = MsgInfo_t::k_EStatsTypeMultiplexedSends;
|
||||
const MsgInfo_t::EStatsType eRawType = MsgInfo_t::k_EStatsTypeMultiplexedSendsRaw;
|
||||
|
||||
// work out a sorted list
|
||||
CUtlMap<uint64, uint32> mapValueToMsg( DefLessFunc( uint64 ) );
|
||||
FOR_EACH_VEC( m_vecMsgInfo, n )
|
||||
{
|
||||
const MsgInfo_t &msgInfo = m_vecMsgInfo[n];
|
||||
|
||||
//see if we are looking for a particular source, and if so, if this has that source set
|
||||
if( nSourceMask && ( msgInfo.stats[ eGroup ][ eMultiType ].nSourceMask & nSourceMask ) == 0 )
|
||||
continue;
|
||||
|
||||
rgTotals[eMultiType].nCount += msgInfo.stats[ eGroup ][ eMultiType ].nCount;
|
||||
rgTotals[eMultiType].uBytes += msgInfo.stats[ eGroup ][ eMultiType ].uBytes;
|
||||
rgTotals[eRawType].nCount += msgInfo.stats[ eGroup ][ eRawType ].nCount;
|
||||
rgTotals[eRawType].uBytes += msgInfo.stats[ eGroup ][ eRawType ].uBytes;
|
||||
|
||||
if ( msgInfo.stats[ eGroup ][ eMultiType ].nCount == 0 )
|
||||
continue;
|
||||
|
||||
uint32 nCount = msgInfo.stats[ eGroup ][ eMultiType ].nCount;
|
||||
uint64 uBytes = msgInfo.stats[ eGroup ][ eMultiType ].uBytes;
|
||||
mapValueToMsg.Insert( bSortByFrequency ? (uint64)nCount : uBytes, n );
|
||||
}
|
||||
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%s", "EMsg MessageName Count % KB % Avg/Msg KBPS Msg Saved % KB Saved %\n" );
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%s", "----- ---------------------------------------------- ---------- ------ -------------- ------ ---------- ---------- ---------- ------ -------------- ------\n" );
|
||||
|
||||
uint32 unTotalMessages = 0;
|
||||
uint64 unTotalBytes = 0;
|
||||
|
||||
for ( uint16 iValue = mapValueToMsg.LastInorder(); iValue != mapValueToMsg.InvalidIndex(); iValue = mapValueToMsg.PrevInorder( iValue ) )
|
||||
{
|
||||
const MsgInfo_t &msgInfo = m_vecMsgInfo[ mapValueToMsg[iValue] ];
|
||||
|
||||
//see if we are looking for a particular source, and if so, if this has that source set
|
||||
if( nSourceMask && ( msgInfo.stats[ eGroup ][ eMultiType ].nSourceMask & nSourceMask ) == 0 )
|
||||
continue;
|
||||
|
||||
uint32 nCount = msgInfo.stats[ eGroup ][ eMultiType ].nCount;
|
||||
uint64 uBytes = msgInfo.stats[ eGroup ][ eMultiType ].uBytes;
|
||||
|
||||
unTotalMessages += nCount;
|
||||
unTotalBytes += uBytes;
|
||||
|
||||
int32 nMessagesSaved = msgInfo.stats[ eGroup ][ eRawType ].nCount - msgInfo.stats[ eGroup ][ eMultiType ].nCount;
|
||||
int64 uBytesSaved = msgInfo.stats[ eGroup ][ eRawType ].uBytes - msgInfo.stats[ eGroup ][ eMultiType ].uBytes;
|
||||
|
||||
uint32 nMessagesIfNotMultiplex = msgInfo.stats[ eGroup ][ eRawType ].nCount;
|
||||
uint64 uBytesIfNotMultiplex = msgInfo.stats[ eGroup ][ eRawType ].uBytes;
|
||||
|
||||
uint32 uAvgMsg = 0;
|
||||
if ( nCount > 0 )
|
||||
uAvgMsg = uBytes / nCount;
|
||||
|
||||
float flCountPerc = 0;
|
||||
if ( rgTotals[eMultiType].nCount > 0 )
|
||||
flCountPerc = nCount * 100.0f / rgTotals[eMultiType].nCount;
|
||||
float flBytesPerc = 0;
|
||||
if ( rgTotals[eMultiType].uBytes > 0 )
|
||||
flBytesPerc = uBytes * 100.0f / rgTotals[eMultiType].uBytes;
|
||||
float fKBPS = 0.0f;
|
||||
if ( ulMicroseconds > 0 )
|
||||
fKBPS = uBytes * 1000.0f / ulMicroseconds;
|
||||
|
||||
float flMessagesSavedPerc = 0.0f;
|
||||
if ( nMessagesIfNotMultiplex > 0 )
|
||||
flMessagesSavedPerc = nMessagesSaved * 100.0f / nMessagesIfNotMultiplex;
|
||||
float flBytesSavedPerc = 0.0f;
|
||||
if ( uBytesIfNotMultiplex > 0 )
|
||||
flBytesSavedPerc = uBytesSaved * 100.0f / uBytesIfNotMultiplex;
|
||||
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "%5u %-46s %10u %5.1f%% %14llu %5.1f%% %10u %10.2f %10d %5.1f%% %14lld %5.1f%%\n",
|
||||
msgInfo.eMsg,
|
||||
msgInfo.pchMsgName,
|
||||
nCount,
|
||||
flCountPerc,
|
||||
uBytes / 1024,
|
||||
flBytesPerc,
|
||||
uAvgMsg,
|
||||
fKBPS,
|
||||
nMessagesSaved,
|
||||
flMessagesSavedPerc,
|
||||
uBytesSaved / 1024,
|
||||
flBytesSavedPerc );
|
||||
}
|
||||
|
||||
uint32 uAvgMsgTotal = 0;
|
||||
if ( unTotalMessages > 0 )
|
||||
uAvgMsgTotal = unTotalBytes / unTotalMessages;
|
||||
|
||||
float fKBPSTotal = 0.0f;
|
||||
if ( ulMicroseconds > 0 )
|
||||
fKBPSTotal = unTotalBytes * 1000.0f / ulMicroseconds;
|
||||
|
||||
float flTotalMessagesPct = 0.0f;
|
||||
if ( rgTotals[eMultiType].nCount > 0 )
|
||||
flTotalMessagesPct = unTotalMessages * 100.0f / rgTotals[eMultiType].nCount;
|
||||
|
||||
float flTotalBytesPct = 0.0f;
|
||||
if ( rgTotals[eMultiType].uBytes > 0 )
|
||||
flTotalBytesPct = unTotalBytes * 100.0f / rgTotals[eMultiType].uBytes;
|
||||
|
||||
int32 nTotalMessagesSaved = rgTotals[eRawType].nCount - rgTotals[eMultiType].nCount;
|
||||
int64 nTotalBytesSaved = rgTotals[eRawType].uBytes - rgTotals[eMultiType].uBytes;
|
||||
|
||||
int32 nTotalMessagesIfNotMultiplex = unTotalMessages - rgTotals[eMultiType].nCount + rgTotals[eRawType].nCount;
|
||||
int64 uTotalBytesIfNotMultiplex = unTotalBytes - rgTotals[eMultiType].uBytes + rgTotals[eRawType].uBytes;
|
||||
|
||||
float flTotalMessagesSavedPct = 0.0f;
|
||||
if ( nTotalMessagesIfNotMultiplex > 0 )
|
||||
flTotalMessagesSavedPct = nTotalMessagesSaved * 100.0f / nTotalMessagesIfNotMultiplex;
|
||||
|
||||
float flTotalBytesSavedPct = 0.0f;
|
||||
if ( uTotalBytesIfNotMultiplex > 0 )
|
||||
flTotalBytesSavedPct = nTotalBytesSaved * 100.0f / uTotalBytesIfNotMultiplex;
|
||||
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "----- ---------------------------------------------- ---------- ------ -------------- ------ ---------- ---------- ---------- ------ -------------- ------\n" );
|
||||
EmitInfo( SPEW_CONSOLE, SPEW_ALWAYS, LOG_ALWAYS, "Totals %10u %5.1f%% %14llu %5.1f%% %10u %10.2f %10d %5.1f%% %14lld %5.1f%%\n",
|
||||
unTotalMessages,
|
||||
flTotalMessagesPct,
|
||||
unTotalBytes / 1024,
|
||||
flTotalBytesPct,
|
||||
uAvgMsgTotal,
|
||||
fKBPSTotal,
|
||||
nTotalMessagesSaved,
|
||||
flTotalMessagesSavedPct,
|
||||
nTotalBytesSaved / 1024,
|
||||
flTotalBytesSavedPct );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Destroys a message list by deallocating everything it's got
|
||||
//-----------------------------------------------------------------------------
|
||||
CMessageList::~CMessageList()
|
||||
{
|
||||
int nUsedBuckets = 0;
|
||||
for ( int nIndex = 0; nIndex < m_vecMessageInfoBuckets.Count(); nIndex++ )
|
||||
{
|
||||
if ( m_vecMessageInfoBuckets[nIndex] != NULL )
|
||||
{
|
||||
FreePv( m_vecMessageInfoBuckets[nIndex] );
|
||||
m_vecMessageInfoBuckets[nIndex] = NULL;
|
||||
nUsedBuckets++;
|
||||
}
|
||||
}
|
||||
|
||||
m_vecMessageInfoBuckets.RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// assure that we've got the slots in the given bucket allocated
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMessageList::AssureBucket( int nBucket )
|
||||
{
|
||||
// if this bucket is bigger then the array, extend the array
|
||||
if ( nBucket >= m_vecMessageInfoBuckets.Count() )
|
||||
{
|
||||
int nOldCount = m_vecMessageInfoBuckets.Count();
|
||||
// message ID "clumps" are usually 100 apart, so we'll try
|
||||
// to grow by 100 each time. Divide 100 by the bucket size and add
|
||||
// one for truncation to figure out our grow-by.
|
||||
int nNewCount = nBucket + (1 + (100 / m_kcBucketSize));
|
||||
|
||||
// get that count
|
||||
m_vecMessageInfoBuckets.EnsureCount( nNewCount );
|
||||
|
||||
// initialize the new ones to NULL
|
||||
for ( int nIndex = nOldCount; nIndex < nNewCount; nIndex++ )
|
||||
{
|
||||
m_vecMessageInfoBuckets[nIndex] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// is the bucket we want allocated?
|
||||
if ( m_vecMessageInfoBuckets[nBucket] == NULL )
|
||||
{
|
||||
// nope; get one and initialize it
|
||||
m_vecMessageInfoBuckets[nBucket] = (short*) PvAlloc( sizeof(short) * m_kcBucketSize );
|
||||
for ( int nIndex = 0; nIndex < m_kcBucketSize; nIndex++)
|
||||
m_vecMessageInfoBuckets[nBucket][nIndex] = -1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Hash an MsgType_t and return the index into m_vecMsgInfo where it can be found
|
||||
// returns -1 if the MsgType_t is unknown
|
||||
//-----------------------------------------------------------------------------
|
||||
short CMessageList::GetMessageIndex( MsgType_t eMsg )
|
||||
{
|
||||
// find the slot and bucket for this message in our hash
|
||||
int nSlot;
|
||||
int nBucket = HashMessage( eMsg, nSlot );
|
||||
|
||||
// taller than the hash?
|
||||
if ( nBucket >= m_vecMessageInfoBuckets.Count() )
|
||||
return -1;
|
||||
|
||||
// not a bucket?
|
||||
if ( m_vecMessageInfoBuckets[nBucket] == NULL )
|
||||
return -1;
|
||||
|
||||
// get the index back to the global array
|
||||
short nIndex = m_vecMessageInfoBuckets[nBucket][nSlot];
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tests to see if a message is valid; if so, return a pointer to its name.
|
||||
// A message must match at least one of the nTypeMask flags to be considered
|
||||
// valid. If provided, ppMsgName is set to k_rgchUnknown if no match,
|
||||
// or the message name if matched.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool CMessageList::GetMessage( MsgType_t eMsg, const char **ppMsgName, int nTypeMask )
|
||||
{
|
||||
VPROF_BUDGET( "GetMessage", VPROF_BUDGETGROUP_JOBS_COROUTINES );
|
||||
|
||||
// if an out variable for the name is provided,
|
||||
// initialize it with a pointer to "unknown" string
|
||||
if ( ppMsgName != NULL )
|
||||
*ppMsgName = k_rgchUnknown;
|
||||
|
||||
short nIndex = GetMessageIndex( eMsg );
|
||||
|
||||
// good index?
|
||||
if ( nIndex == -1 )
|
||||
{
|
||||
if ( ppMsgName != NULL )
|
||||
{
|
||||
*ppMsgName = "Unknown MsgType - Not Found";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const MsgInfo_t &msgInfo = m_vecMsgInfo[nIndex];
|
||||
|
||||
// get the string out
|
||||
if ( ppMsgName != NULL )
|
||||
*ppMsgName = msgInfo.pchMsgName;
|
||||
|
||||
// it's good if it matches the flags
|
||||
return ( 0 != ( msgInfo.nFlags & nTypeMask ) );
|
||||
}
|
||||
|
||||
|
||||
} // namespace GCSDK
|
||||
|
||||
Reference in New Issue
Block a user