music: fix song build bottleneck
Fix redundant separator parsing obliterating loading performance. If there are no separators configured, the parsing function would not short-circuit and instead do a useless O(n) iteraton (including escaping!), massively reducing performance. Song build performance still isn't the best (blame intelligent sorting), but it's definitely better now.
This commit is contained in:
parent
f9ccb831d8
commit
a37df594e7
5 changed files with 15 additions and 3 deletions
|
@ -10,6 +10,7 @@
|
|||
- Albums implicitly linked only via "artist" tags are now placed in a special
|
||||
"appears on" section in the artist view
|
||||
- Album covers that are not 1:1 aspect ratio are no longer cropped
|
||||
- Optimized library creation phase of the music loading process
|
||||
|
||||
#### What's Fixed
|
||||
- Prevented options such as "Add to queue" from being selected on empty artists and playlists
|
||||
|
|
|
@ -365,6 +365,10 @@ constructor(
|
|||
throw NoAudioPermissionException()
|
||||
}
|
||||
|
||||
// TODO: Parallelize this even more aggressively. I can hypothetically connect all
|
||||
// finalization steps (library, cache, playlists) into a single pipeline would need
|
||||
// to change how I indicate progress however
|
||||
|
||||
// Start initializing the extractors. Use an indeterminate state, as there is no ETA on
|
||||
// how long a media database query will take.
|
||||
emitLoading(IndexingProgress.Indeterminate)
|
||||
|
|
|
@ -177,9 +177,12 @@ private class DeviceLibraryImpl(rawSongs: List<RawSong>, settings: MusicSettings
|
|||
* @return A sorted list of [SongImpl]s derived from the [RawSong] that should be suitable for
|
||||
* grouping.
|
||||
*/
|
||||
private fun buildSongs(rawSongs: List<RawSong>, settings: MusicSettings) =
|
||||
Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING)
|
||||
private fun buildSongs(rawSongs: List<RawSong>, settings: MusicSettings): List<Song> {
|
||||
val songs = Sort(Sort.Mode.ByName, Sort.Direction.ASCENDING)
|
||||
.songs(rawSongs.map { SongImpl(it, settings) }.distinctBy { it.uid })
|
||||
logD("Successfully built ${songs.size} songs")
|
||||
return songs
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a list of [Album]s from the given [Song]s.
|
||||
|
|
|
@ -174,6 +174,8 @@ private data class IntelligentKnownName(override val raw: String, override val s
|
|||
override val sortTokens = parseTokens(sort ?: raw)
|
||||
|
||||
private fun parseTokens(name: String): List<SortToken> {
|
||||
// TODO: This routine is consuming much of the song building runtime, find a way to
|
||||
// optimize it
|
||||
val stripped =
|
||||
name
|
||||
// Remove excess punctuation from the string, as those u
|
||||
|
|
|
@ -39,6 +39,8 @@ fun List<String>.parseMultiValue(settings: MusicSettings) =
|
|||
this
|
||||
}
|
||||
|
||||
// TODO: Remove the escaping checks, it's too expensive to do this for every single tag.
|
||||
|
||||
/**
|
||||
* Split a [String] by the given selector, automatically handling escaped characters that satisfy
|
||||
* the selector.
|
||||
|
@ -106,7 +108,7 @@ fun List<String>.correctWhitespace() = mapNotNull { it.correctWhitespace() }
|
|||
* @return A list of one or more [String]s that were split up by the user-defined separators.
|
||||
*/
|
||||
private fun String.maybeParseBySeparators(settings: MusicSettings): List<String> {
|
||||
// Get the separators the user desires. If null, there's nothing to do.
|
||||
if (settings.multiValueSeparators.isEmpty()) return listOf(this)
|
||||
return splitEscaped { settings.multiValueSeparators.contains(it) }.correctWhitespace()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue