[Kernel] Remember APR paths absent from the read-only game image
Looking up a resolved path's size stats the host filesystem, and a path that is not there costs two stats (a file probe and a directory probe) every single time it is asked for. A resource streamer asks for far more paths than the image contains, so misses are the common case and they are repeated. /app0 is the read-only game image: a path that is not in it now will not appear later. Absent paths under that root are therefore remembered, which turns the repeated pair of host stats on what is often a slow external volume into a dictionary probe. Paths outside /app0 can be created at run time and are not remembered.
This commit is contained in:
parent
7a42dbbf14
commit
66304399ae
|
|
@ -6883,6 +6883,19 @@ public static partial class KernelMemoryCompatExports
|
|||
return TryWriteHostPathStat(ctx, statAddress, hostPath, isDirectory);
|
||||
}
|
||||
|
||||
// /app0 is the read-only game image, so a path that is not in it now will not
|
||||
// appear later. Remembering the absent ones turns a repeated pair of host stats
|
||||
// on the (slow, external) game volume into a dictionary probe; Demon's Souls
|
||||
// resolves tens of thousands of paths per boot and misses are the common case.
|
||||
private static readonly ConcurrentDictionary<string, byte> _aprMissingImagePaths = new(HostFsPath.Comparer);
|
||||
|
||||
private static bool IsUnderApp0(string cachePath)
|
||||
{
|
||||
var app0Root = ResolveApp0Root();
|
||||
return !string.IsNullOrWhiteSpace(app0Root) &&
|
||||
cachePath.StartsWith(Path.TrimEndingDirectorySeparator(app0Root) + Path.DirectorySeparatorChar, HostFsPath.Comparison);
|
||||
}
|
||||
|
||||
private static bool TryGetAprFileSize(string hostPath, out ulong size)
|
||||
{
|
||||
size = 0;
|
||||
|
|
@ -6902,6 +6915,11 @@ public static partial class KernelMemoryCompatExports
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_aprMissingImagePaths.ContainsKey(cachePath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// One directory listing returns every file's size; titles resolve whole asset
|
||||
// directories at startup, so this replaces one host query per file.
|
||||
if (Path.GetDirectoryName(cachePath) is { } directory && _aprScannedDirectories.TryAdd(directory, 0))
|
||||
|
|
@ -6936,6 +6954,11 @@ public static partial class KernelMemoryCompatExports
|
|||
|
||||
if (!new DirectoryInfo(cachePath).Exists)
|
||||
{
|
||||
if (IsUnderApp0(cachePath))
|
||||
{
|
||||
_aprMissingImagePaths.TryAdd(cachePath, 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue