[Fix] Implement efficient directory query in handleGetMusicDirectoryRequest() - #880
Open
JonnieCache wants to merge 3 commits into
Open
JonnieCache wants to merge 3 commits into
JonnieCache wants to merge 3 commits into
Conversation
Returns the releases held by the direct children of a directory in a single query, for callers that list a directory and need each child's release.
The subdirectory loop looked up each child's release separately, so listing a directory cost one query per child, each in its own nested transaction. Resolve them all up front instead.
JonnieCache
force-pushed
the
subsonic-child-releases
branch
from
August 18, 2026 18:17
77ec387 to
3e2258b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
The current
handleGetMusicDirectoryRequest()function, the handler for the/getMusicDirectoryendpoint in the subsonic API does an N+1 query pattern when looking up the releases for the subdirectories of a queried directory. When querying a directory with N children, you get N additionalRelease::findqueries. Each gets their own nested db transaction. This is very slow.The change
This PR adds
Directory::findChildReleases()which returns all releases for direct children of a given directory in a single query.As this is intended as a unified query interface for both the subsonic API and my upcoming second attempt at the Folder Browsing UI, I return a vector of
ChildReleasestructs containing theReleaseas well as the count of releases found inside the directory. This so that the folder UI can direct-link to the release only if it's alone in its directory, whereas subsonic wants to link an arbitrary release even if there are several candidates.Performance
I measured on a raspberry pi 4 using the
Dockerfile-releasecontainer, calling/getMusicDirectorywith my real database file, with some large directories with a lot of subdirs. I observed a 1.26x mean speedup.I also noted that it's still very slow on the raspi, with the biggest dir going from 3253ms to 2780ms. This is because
createAlbumNode()runs 8 further database queries per-release to retrieve Genre, Mood and so on, essentially the same problem this PR solves but more so. The solution would be to do all of this in one large chain of JOINs and have sqlite sort it all out inside one query. This will be a lot faster.