From e0d0292482f43fa955c9900da536ed2ae06c2d28 Mon Sep 17 00:00:00 2001 From: Biroj Date: Sun, 21 Jan 2024 04:33:31 +0000 Subject: [PATCH 1/4] Avoiding processing same cert file to improve cold start performance across Linux distros. --- .../OpenSslCachedSystemStoreProvider.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs index 409170a40f2656..3137d82acf4fcd 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs @@ -149,6 +149,7 @@ private static Tuple LoadMachineStores var uniqueRootCerts = new HashSet(); var uniqueIntermediateCerts = new HashSet(); + var processedFiles = new HashSet(); bool firstLoad = (s_nativeCollections == null); if (firstLoad) @@ -216,6 +217,12 @@ bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false) return false; } + string originalFile = Interop.Sys.ReadLink(file) ?? file; + if (processedFiles.Contains(originalFile)) + { + return true; + } + using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file, "rb")) { // The handle may be invalid, for example when we don't have read permission for the file. @@ -281,6 +288,11 @@ bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false) } } + if (readData) + { + processedFiles.Add(originalFile); + } + return readData; } From 87fbdaeabcb513cb576353ddcfb9c4410393d83d Mon Sep 17 00:00:00 2001 From: Biroj Date: Mon, 22 Jan 2024 05:04:22 +0000 Subject: [PATCH 2/4] Added Tuple to reuse FileStatus details --- .../OpenSslCachedSystemStoreProvider.cs | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs index 3137d82acf4fcd..e16bd7d22cf67b 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs @@ -149,7 +149,7 @@ private static Tuple LoadMachineStores var uniqueRootCerts = new HashSet(); var uniqueIntermediateCerts = new HashSet(); - var processedFiles = new HashSet(); + var processedFiles = new HashSet<(long Ino, long Dev)>(); bool firstLoad = (s_nativeCollections == null); if (firstLoad) @@ -207,20 +207,20 @@ bool ProcessDir(string dir, out DateTime lastModified) bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false) { bool readData = false; + bool result = TryStatFile(file, out lastModified, out (long, long) fileDetails); if (skipStat) { lastModified = default; } - else if (!TryStatFile(file, out lastModified)) + else if (!result) { return false; } - string originalFile = Interop.Sys.ReadLink(file) ?? file; - if (processedFiles.Contains(originalFile)) + if (processedFiles.Contains(fileDetails)) { - return true; + return true; } using (SafeBioHandle fileBio = Interop.Crypto.BioNewFile(file, "rb")) @@ -288,9 +288,9 @@ bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false) } } - if (readData) + if (readData) { - processedFiles.Add(originalFile); + processedFiles.Add(fileDetails); } return readData; @@ -319,7 +319,6 @@ bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false) // In order to maintain "finalization-free" the GetNativeCollections method would need to // DangerousAddRef, and the callers would need to DangerousRelease, adding more interlocked operations // on every call. - Volatile.Write(ref s_nativeCollections, newCollections); s_recheckStopwatch.Restart(); return newCollections; @@ -374,12 +373,19 @@ private static string[] GetRootStoreDirectories(out bool isDefault) } private static bool TryStatFile(string path, out DateTime lastModified) - => TryStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified); + => CallStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified).HasCallSucceed; private static bool TryStatDirectory(string path, out DateTime lastModified) - => TryStat(path, Interop.Sys.FileTypes.S_IFDIR, out lastModified); + => CallStat(path, Interop.Sys.FileTypes.S_IFDIR, out lastModified).HasCallSucceed; + + private static bool TryStatFile(string path, out DateTime lastModified, out (long Ino, long Dev) fileDetails) + { + var statResult = CallStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified); + fileDetails = (statResult.fileStatus.Ino, statResult.fileStatus.Dev); + return statResult.HasCallSucceed; + } - private static bool TryStat(string path, int fileType, out DateTime lastModified) + private static (bool HasCallSucceed, Interop.Sys.FileStatus fileStatus) CallStat(string path, int fileType, out DateTime lastModified) { lastModified = default; @@ -388,11 +394,11 @@ private static bool TryStat(string path, int fileType, out DateTime lastModified if (Interop.Sys.Stat(path, out status) < 0 || (status.Mode & Interop.Sys.FileTypes.S_IFMT) != fileType) { - return false; + return (false, status); } lastModified = DateTime.UnixEpoch + TimeSpan.FromTicks(status.MTime * TimeSpan.TicksPerSecond + status.MTimeNsec / TimeSpan.NanosecondsPerTick); - return true; + return (true, status); } } } From 9efa5b7b0df86b6f988ce2491f86de043ae6cf9d Mon Sep 17 00:00:00 2001 From: Biroj Date: Mon, 22 Jan 2024 09:27:52 +0000 Subject: [PATCH 3/4] Incorporated feedback --- .../OpenSslCachedSystemStoreProvider.cs | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs index e16bd7d22cf67b..34c3d7527033df 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs @@ -198,27 +198,21 @@ bool ProcessDir(string dir, out DateTime lastModified) foreach (string file in Directory.EnumerateFiles(dir)) { - hasStoreData |= ProcessFile(file, out _, skipStat: true); + hasStoreData |= ProcessFile(file, out _); } return hasStoreData; } - bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false) + bool ProcessFile(string file, out DateTime lastModified) { bool readData = false; - bool result = TryStatFile(file, out lastModified, out (long, long) fileDetails); - - if (skipStat) - { - lastModified = default; - } - else if (!result) + if (!TryStatFile(file, out lastModified, out (long, long) fileId)) { return false; } - if (processedFiles.Contains(fileDetails)) + if (processedFiles.Contains(fileId)) { return true; } @@ -290,7 +284,7 @@ bool ProcessFile(string file, out DateTime lastModified, bool skipStat = false) if (readData) { - processedFiles.Add(fileDetails); + processedFiles.Add(fileId); } return readData; @@ -373,32 +367,28 @@ private static string[] GetRootStoreDirectories(out bool isDefault) } private static bool TryStatFile(string path, out DateTime lastModified) - => CallStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified).HasCallSucceed; + => CallStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified, out _); private static bool TryStatDirectory(string path, out DateTime lastModified) - => CallStat(path, Interop.Sys.FileTypes.S_IFDIR, out lastModified).HasCallSucceed; + => CallStat(path, Interop.Sys.FileTypes.S_IFDIR, out lastModified, out _); - private static bool TryStatFile(string path, out DateTime lastModified, out (long Ino, long Dev) fileDetails) - { - var statResult = CallStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified); - fileDetails = (statResult.fileStatus.Ino, statResult.fileStatus.Dev); - return statResult.HasCallSucceed; - } + private static bool TryStatFile(string path, out DateTime lastModified, out (long, long) fileId) + => CallStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified, out fileId); - private static (bool HasCallSucceed, Interop.Sys.FileStatus fileStatus) CallStat(string path, int fileType, out DateTime lastModified) + private static bool CallStat(string path, int fileType, out DateTime lastModified, out (long, long) fileId) { lastModified = default; - - Interop.Sys.FileStatus status; + fileId = default; // Use Stat to follow links. - if (Interop.Sys.Stat(path, out status) < 0 || + if (Interop.Sys.Stat(path, out Interop.Sys.FileStatus status) < 0 || (status.Mode & Interop.Sys.FileTypes.S_IFMT) != fileType) { - return (false, status); + return false; } + fileId = (status.Ino, status.Dev); lastModified = DateTime.UnixEpoch + TimeSpan.FromTicks(status.MTime * TimeSpan.TicksPerSecond + status.MTimeNsec / TimeSpan.NanosecondsPerTick); - return (true, status); + return true; } } } From 3f0980a00a4251d7e5127acd2982721c83b47fb1 Mon Sep 17 00:00:00 2001 From: Biroj Date: Mon, 22 Jan 2024 17:25:03 +0000 Subject: [PATCH 4/4] Kept the name same TryStat --- .../OpenSslCachedSystemStoreProvider.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs index 34c3d7527033df..1aa22406e4fd4e 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCachedSystemStoreProvider.cs @@ -114,7 +114,7 @@ private static bool LastWriteTimesHaveChanged() if (s_rootStoreFile != null) { - _ = TryStatFile(s_rootStoreFile, out DateTime lastModified); + _ = TryStatFile(s_rootStoreFile, out DateTime lastModified, out _); if (lastModified != s_fileLastWrite) { return true; @@ -366,16 +366,13 @@ private static string[] GetRootStoreDirectories(out bool isDefault) return directories; } - private static bool TryStatFile(string path, out DateTime lastModified) - => CallStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified, out _); - private static bool TryStatDirectory(string path, out DateTime lastModified) - => CallStat(path, Interop.Sys.FileTypes.S_IFDIR, out lastModified, out _); + => TryStat(path, Interop.Sys.FileTypes.S_IFDIR, out lastModified, out _); private static bool TryStatFile(string path, out DateTime lastModified, out (long, long) fileId) - => CallStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified, out fileId); + => TryStat(path, Interop.Sys.FileTypes.S_IFREG, out lastModified, out fileId); - private static bool CallStat(string path, int fileType, out DateTime lastModified, out (long, long) fileId) + private static bool TryStat(string path, int fileType, out DateTime lastModified, out (long, long) fileId) { lastModified = default; fileId = default;