Optimize. This brings the ALL_COURSES sort time down. I didn't check the time

spent in this code in release, but in debug this brings the time spent building
musicwheel items in ALL_COURSES sort mode from 30 seconds with my 1600+
songs in about 80 groups down to 12 seconds. Release is down to 6 seconds,
but I don't know where it was to start. This time would increase nearly
exponentially with the number of songs and groups.
This commit is contained in:
Thad Ward
2005-10-30 21:07:50 +00:00
parent 3c11c86ea9
commit df136da381
+53 -56
View File
@@ -512,6 +512,33 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail )
/* Set to true if CourseDifficulty is able to change something. */
bool bCourseDifficultyIsSignificant = (cd == DIFFICULTY_MEDIUM);
// get a list of all songs that are 1 stage long
vector<Song*> vpAllPossibleSongs;
SONGMAN->GetSongs(vpAllPossibleSongs, 1);
// remove locked and tutorial songs from the list
FOREACH( Song*, vpAllPossibleSongs, song )
{
// Ignore locked songs when choosing randomly
// TODO: Move Course initialization after UNLOCKMAN is created
if( UNLOCKMAN && UNLOCKMAN->SongIsLocked(*song) )
{
vector<Song*>::iterator eraseme = song;
song--;
vpAllPossibleSongs.erase( eraseme );
continue;
}
// Ignore boring tutorial songs
if( (*song)->IsTutorial() )
{
vector<Song*>::iterator eraseme = song;
song--;
vpAllPossibleSongs.erase( eraseme );
continue;
}
}
// Resolve each entry to a Song and Steps.
FOREACH_CONST( CourseEntry, entries, e )
{
@@ -524,77 +551,41 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail )
// Start with all songs
vector<Song*> vpPossibleSongs;
vector<Steps*> vpPossibleSteps;
if( e->pSong )
{
// Choose an exact song
vpPossibleSongs.push_back( e->pSong );
// Choose an exact song, if we have matching steps and all
e->pSong->GetSteps( vpPossibleSteps, st, e->baseDifficulty, e->iLowMeter, e->iHighMeter );
if( ( !e->sSongGroup.empty() && (*song)->m_sGroupName == e->sSongGroup ) && !vpPossibleSteps.empty() )
{
pResolvedSong = e->pSong;
}
else
{
vpPossibleSongs = SONGMAN->GetAllSongs();
FOREACH( Song*, vpPossibleSongs, song )
{
// Ignore locked songs when choosing randomly
// TODO: Move Course initialization after UNLOCKMAN is created
if( UNLOCKMAN && UNLOCKMAN->SongIsLocked(*song) )
{
vector<Song*>::iterator eraseme = song;
song--;
vpPossibleSongs.erase( eraseme );
continue;
}
// Ignore boring tutorial songs
if( (*song)->IsTutorial() )
{
vector<Song*>::iterator eraseme = song;
song--;
vpPossibleSongs.erase( eraseme );
continue;
}
// Don't allow long songs
if( SONGMAN->GetNumStagesForSong(*song) > 1 )
{
vector<Song*>::iterator eraseme = song;
song--;
vpPossibleSongs.erase( eraseme );
continue;
}
}
}
// Filter out all songs that don't have matching steps
// At the same time, create a list of matching song/steps.
typedef vector<Steps*> StepsVector;
map<Song*,StepsVector> mapSongToSteps;
FOREACH( Song*, vpPossibleSongs, song )
else
{
// copy over any songs that match our group filter, if one is set, and match our
// steps filter.
FOREACH( Song*, vpAllPossibleSongs, song )
{
// Apply song group filter
if( !e->sSongGroup.empty() && (*song)->m_sGroupName != e->sSongGroup )
{
vector<Song*>::iterator eraseme = song;
song--;
vpPossibleSongs.erase( eraseme );
continue;
}
vector<Steps*> vpMatchingSteps;
(*song)->GetSteps( vpMatchingSteps, st, e->baseDifficulty, e->iLowMeter, e->iHighMeter );
if( vpMatchingSteps.empty() )
{
vector<Song*>::iterator eraseme = song;
song--;
vpPossibleSongs.erase( eraseme );
continue;
vpPossibleSongs.push_back( *song );
}
mapSongToSteps[*song] = vpMatchingSteps;
}
// if there are no songs to choose from, abort now
if( vpPossibleSongs.empty() )
continue;
// TODO: Move Course initialization after PROFILEMAN is created
switch( e->songSort )
@@ -623,12 +614,18 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail )
if( e->iChooseIndex < int(vpPossibleSongs.size()) )
{
pResolvedSong = vpPossibleSongs[e->iChooseIndex];
vector<Steps*> &vpPossibleSteps = mapSongToSteps[pResolvedSong];
ASSERT( !vpPossibleSteps.empty() ); // if no steps are playable, this shouldn't be a possible song
random_shuffle( vpPossibleSteps.begin(), vpPossibleSteps.end(), rnd );
pResolvedSteps = vpPossibleSteps[0];
pResolvedSong->GetSteps( vpPossibleSteps, st, e->baseDifficulty, e->iLowMeter, e->iHighMeter );
}
else
{
continue;
}
}
ASSERT( !vpPossibleSteps.empty() ); // if no steps are playable, this shouldn't be a possible song
if( vpPossibleSteps.size() > 1 ) // no reason to randomize if there's only one set of possible steps
random_shuffle( vpPossibleSteps.begin(), vpPossibleSteps.end(), rnd );
pResolvedSteps = vpPossibleSteps[0];
if( pResolvedSong == NULL || pResolvedSteps == NULL )
continue; // this song entry isn't playable. Skip.