From a1681faa06c9a9b936346922b95c798210c66209 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sat, 4 Jun 2011 17:28:20 +0700 Subject: [PATCH 1/2] skip recalculating radar values and last beat when loading from cache. loading songs from the cache is now 5x faster. fyi: it took 1:40 minutes to load my library, now it's only 20 seconds. --- src/NotesLoaderSM.cpp | 2 +- src/Song.cpp | 18 ++++++++++++------ src/Song.h | 4 ++-- src/Steps.cpp | 10 +++++++++- src/Steps.h | 1 + 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 78a6734eec..acb7b5d0c7 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -964,7 +964,7 @@ void SMLoader::TidyUpData( Song &song, bool bFromCache ) bg.push_back( BackgroundChange(song.m_fLastBeat,song.m_sBackgroundFile) ); } while(0); } - song.TidyUpData(); + song.TidyUpData( bFromCache ); } /* diff --git a/src/Song.cpp b/src/Song.cpp index 059190c751..491dfb477e 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -236,9 +236,7 @@ bool Song::LoadFromSongDir( RString sDir ) { // LOG->Trace( "Loading '%s' from cache file '%s'.", m_sSongDir.c_str(), GetCacheFilePath().c_str() ); bool bLoadedFromSSC = SSCLoader::LoadFromSSCFile( sCacheFilePath, *this, true ); - if( bLoadedFromSSC ) - SSCLoader::TidyUpData( *this, true ); - else + if( !bLoadedFromSSC ) { // load from .sm SMLoader::LoadFromSMFile( sCacheFilePath, *this, true ); @@ -390,7 +388,7 @@ void FixupPath( RString &path, const RString &sSongPath ) } // Songs in BlacklistImages will never be autodetected as song images. -void Song::TidyUpData() +void Song::TidyUpData( bool bFromCache ) { // We need to do this before calling any of HasMusic, HasHasCDTitle, etc. ASSERT_M( m_sSongDir.Left(3) != "../", m_sSongDir ); // meaningless @@ -481,7 +479,7 @@ void Song::TidyUpData() /* Generate these before we autogen notes, so the new notes can inherit * their source's values. */ - ReCalculateRadarValuesAndLastBeat(); + ReCalculateRadarValuesAndLastBeat( bFromCache ); Trim( m_sMainTitle ); Trim( m_sSubTitle ); @@ -791,8 +789,16 @@ void Song::TranslateTitles() title.SaveToStrings( m_sMainTitle, m_sSubTitle, m_sArtist, m_sMainTitleTranslit, m_sSubTitleTranslit, m_sArtistTranslit ); } -void Song::ReCalculateRadarValuesAndLastBeat() +void Song::ReCalculateRadarValuesAndLastBeat( bool bFromCache ) { + if( bFromCache && m_fFirstBeat >= 0 && m_fLastBeat > 0 ) + { + // this is loaded from cache, then we just have to calculate the radar values. + for( unsigned i=0; iCalculateRadarValues( m_fMusicLengthSeconds ); + return; + } + float fFirstBeat = FLT_MAX; // inf float fLastBeat = m_fSpecifiedLastBeat; // Make sure we're at least as long as the specified amount. diff --git a/src/Song.h b/src/Song.h index 825e7e2dc4..7d3e92fab9 100644 --- a/src/Song.h +++ b/src/Song.h @@ -97,13 +97,13 @@ public: bool ReloadFromSongDir( RString sDir ); /** @brief Call this after loading a song to clean up invalid data. */ - void TidyUpData(); + void TidyUpData( bool bFromCache = false ); /** * @brief Get the new radar values, and determine the last beat at the same time. * * This is called by TidyUpData, after saving the Song. */ - void ReCalculateRadarValuesAndLastBeat(); + void ReCalculateRadarValuesAndLastBeat( bool bFromCache = false ); /** * @brief Translate any titles that aren't in english. * diff --git a/src/Steps.cpp b/src/Steps.cpp index de2634e83c..c1a79064f5 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -31,7 +31,8 @@ Steps::Steps(): m_StepsType(StepsType_Invalid), m_sNoteDataCompressed(""), m_sFilename(""), m_bSavedToDisk(false), m_LoadedFromProfile(ProfileSlot_Invalid), m_iHash(0), m_sDescription(""), m_sChartStyle(""), - m_Difficulty(Difficulty_Invalid), m_iMeter(0), m_sCredit("") {} + m_Difficulty(Difficulty_Invalid), m_iMeter(0), m_sCredit(""), + m_bAreCachedRadarValuesJustLoaded(false) {} Steps::~Steps() { @@ -171,6 +172,12 @@ void Steps::CalculateRadarValues( float fMusicLengthSeconds ) if( parent != NULL ) return; + if( m_bAreCachedRadarValuesJustLoaded ) + { + m_bAreCachedRadarValuesJustLoaded = false; + return; + } + // Do write radar values, and leave it up to the reading app whether they want to trust // the cached values without recalculating them. /* @@ -422,6 +429,7 @@ void Steps::SetCachedRadarValues( const RadarValues v[NUM_PLAYERS] ) { DeAutogen(); copy( v, v + NUM_PLAYERS, m_CachedRadarValues ); + m_bAreCachedRadarValuesJustLoaded = true; } bool Steps::UsesSplitTiming() const diff --git a/src/Steps.h b/src/Steps.h index 1e107f7db4..8ba508b9d2 100644 --- a/src/Steps.h +++ b/src/Steps.h @@ -180,6 +180,7 @@ private: int m_iMeter; /** @brief The radar values used for each player. */ RadarValues m_CachedRadarValues[NUM_PLAYERS]; + bool m_bAreCachedRadarValuesJustLoaded; /** @brief The name of the person who created the Steps. */ RString m_sCredit; }; From 49042c4878554dc401ca06e1e305f079fd26c226 Mon Sep 17 00:00:00 2001 From: Thai Pangsakulyanont Date: Sat, 4 Jun 2011 19:02:45 +0700 Subject: [PATCH 2/2] try to improve performance with scroll segments: - optimize GetDisplayedBeat (seems to be a bottleneck here). - make sure that fFirstBeatToDraw <= fBeat <= fLastBeatToDraw in IS_ON_SCREEN. --- src/NoteField.cpp | 2 +- src/TimingData.cpp | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 8b9684d2d1..29a08e081a 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -832,7 +832,7 @@ void NoteField::DrawPrimitives() //LOG->Trace( "start = %f.1, end = %f.1", fFirstBeatToDraw-fSongBeat, fLastBeatToDraw-fSongBeat ); //LOG->Trace( "Drawing elements %d through %d", iFirstRowToDraw, iLastRowToDraw ); -#define IS_ON_SCREEN( fBeat ) IsOnScreen( fBeat, 0, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels ) +#define IS_ON_SCREEN( fBeat ) ( fFirstBeatToDraw <= (fBeat) && (fBeat) <= fLastBeatToDraw && IsOnScreen( fBeat, 0, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels ) ) // Draw board if( SHOW_BOARD ) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index 8e1672e580..0abe04e4ff 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -1002,11 +1002,19 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const float TimingData::GetDisplayedBeat( float fBeat ) const { - unsigned index = GetScrollSegmentIndexAtBeat(fBeat); - float fOutBeat = ( fBeat - NoteRowToBeat(m_ScrollSegments[index].m_iStartRow) ) * m_ScrollSegments[index].m_fPercent; - for( unsigned i = 0; i < index; i ++ ) + vector::const_iterator it = m_ScrollSegments.begin(), end = m_ScrollSegments.end(); + float fOutBeat = 0.0; + for( ; it != end; it++ ) { - fOutBeat += ( NoteRowToBeat(m_ScrollSegments[i + 1].m_iStartRow) - NoteRowToBeat(m_ScrollSegments[i].m_iStartRow) ) * m_ScrollSegments[i].m_fPercent; + if( it+1 == end || BeatToNoteRow(fBeat) <= (it+1)->m_iStartRow ) + { + fOutBeat += ( fBeat - NoteRowToBeat((it)->m_iStartRow) ) * (it)->m_fPercent; + break; + } + else + { + fOutBeat += ( NoteRowToBeat((it+1)->m_iStartRow) - NoteRowToBeat((it)->m_iStartRow) ) * (it)->m_fPercent; + } } return fOutBeat; }