New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unnecessary stat()s in external audio & subtitle scans make playback start slow (~50 seconds) #21193
Comments
Same here, it looks like Kodi also tries to download the whole file from the HTTPS server to scan for subtitles, then load the video, and the process lasting time depends on the file size. Kodi Version: 19.4 |
I think I'm pointing at a narrower problem than asinitial is? I'm specifically pointing at the problem of I can work around the performance problem with this kludge: --- a/xbmc/platform/posix/filesystem/PosixDirectory.cpp
+++ b/xbmc/platform/posix/filesystem/PosixDirectory.cpp
@@ -25,6 +25,22 @@ CPosixDirectory::CPosixDirectory(void) = default;
CPosixDirectory::~CPosixDirectory(void) = default;
+// Until C++20
+static bool endsWith(const std::string& s, const std::string& suffix)
+{
+ return s.size() >= suffix.size() && s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
+}
+
+// Live dangerously! Boldly assume that names ending in these extensions are files
+// and not directories! We do this because these stat calls to confirm the file type
+// are sooooo slooooooooooow, and just make using Kodi not very much fun. :(
+static bool dangerouslyAssumeIsFile(const std::string& name) {
+ for (auto &ext : { ".ass", ".avi", ".jpg", ".mkv", ".mp4", ".mpeg", ".ogm", ".ssa", ".webm", ".webp"})
+ if (endsWith(name, ext))
+ return true;
+ return false;
+}
+
bool CPosixDirectory::GetDirectory(const CURL& url, CFileItemList &items)
{
std::string root = url.Get();
@@ -54,7 +70,7 @@ bool CPosixDirectory::GetDirectory(const CURL& url, CFileItemList &items)
// is not equal to the (correct) stat() obtained one. In this case the file type
// could not be determined and the value of dirent.d_type is set to DT_UNKNOWN.
// In order to get a correct value we have to incur the cost of calling stat.
- if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK)
+ if ((entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) && !dangerouslyAssumeIsFile(entry->d_name))
{
if (stat(itemPath.c_str(), &buffer) == 0)
bStat = true; |
Bug report
Describe the bug
Here is a clear and concise description of what the problem is:
On TV show playback start, Kodi calls
stat()
on every media file and thumbnail in the same directory as the media file selected for playback, one file at a time. This can delay playback start significantly, especially when playing from a networked filesystem where astat()
call can take 10ms. For example:792 episodes * 2 files/episode (media and thumbnail) * 3 stats/file (two scans for subtitles + a scan for separate audio) * 10ms = 47 seconds, a long time to display the loading spinner waiting for playback to begin.
Splitting by seasons helps a little bit: 365 episodes * 2 * 3 * 10ms = 22 seconds, but it's still quite a delay.
These stat calls are unnecessary. After collecting all this stat info,
ScanPathsForAssociatedItems
filters by filename and discards all of it that's not related to the media being played. The filenames are collected by the much, much fastergetdents
call -- thestat
data from all the other files is never used.Two example stack traces of these stat calls:
and
Expected Behavior
Here is a clear and concise description of what was expected to happen:
Playback should start quickly, showing a spinner for less than 1 second.
Actual Behavior
A loading spinner is displayed for 10s of seconds before playback begins. Playback start gets slower and slower as more episodes are added.
Possible Fix
Stat lazily? Pass a path prefix to
GetItemsToScan
?To Reproduce
Steps to reproduce the behavior:
Debuglog
The debuglog can be found here: kodi-slow.log
Also, here's an strace log showing 4781 sequential
stat
s from one thread (average stat time 11.5 ms), statting every file three times, blocking playback start for 55 seconds:kodi-slow-one-thread-strace.log
Additional context or screenshots (if appropriate)
Here is some additional context or explanation that might help:
It looks like #20471 (scan for external subtitles once instead of twice) will reduce the delay by a third (3 scans → 2 scans) when it makes its way into a release. This will help reduce the impact of this, but doesn't address the core problem that unrelated files are unnecessarilly
stat
ed.Your Environment
Used Operating system:
Android
iOS
tvOS
Linux
OSX
Windows
Windows UWP
Operating system version/name: NixOS 21.11.334247.573095944e7
Kodi version: 19.4
note: Once the issue is made we require you to update it with new information or Kodi versions should that be required.
Team Kodi will consider your problem report however, we will not make any promises the problem will be solved.
The text was updated successfully, but these errors were encountered: