Remove a few string allocations from System.IO.FileSystem (#34551)
authorStephen Toub <stoub@microsoft.com>
Sun, 5 Apr 2020 11:41:49 +0000 (07:41 -0400)
committerGitHub <noreply@github.com>
Sun, 5 Apr 2020 11:41:49 +0000 (07:41 -0400)
src/libraries/System.IO.FileSystem/src/System/IO/Directory.cs
src/libraries/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs

index f72db3a..e9b21f8 100644 (file)
@@ -262,25 +262,26 @@ namespace System.IO
             string fulldestDirName = Path.GetFullPath(destDirName);
             string destPath = PathInternal.EnsureTrailingSeparator(fulldestDirName);
 
-            string sourceDirNameFromFullPath = Path.GetFileName(fullsourceDirName);
-            string destDirNameFromFullPath = Path.GetFileName(fulldestDirName);
+            ReadOnlySpan<char> sourceDirNameFromFullPath = Path.GetFileName(fullsourceDirName.AsSpan());
+            ReadOnlySpan<char> destDirNameFromFullPath = Path.GetFileName(fulldestDirName.AsSpan());
 
             StringComparison fileSystemSensitivity = PathInternal.StringComparison;
-            bool directoriesAreCaseVariants = !string.Equals(sourceDirNameFromFullPath, destDirNameFromFullPath, StringComparison.Ordinal)
-                && string.Equals(sourceDirNameFromFullPath, destDirNameFromFullPath, StringComparison.OrdinalIgnoreCase);
-            bool sameDirectoryDifferentCase = directoriesAreCaseVariants
-                                                && string.Equals(destDirNameFromFullPath, sourceDirNameFromFullPath, fileSystemSensitivity);
+            bool directoriesAreCaseVariants =
+                !sourceDirNameFromFullPath.SequenceEqual(destDirNameFromFullPath) &&
+                sourceDirNameFromFullPath.Equals(destDirNameFromFullPath, StringComparison.OrdinalIgnoreCase);
+            bool sameDirectoryDifferentCase =
+                directoriesAreCaseVariants &&
+                destDirNameFromFullPath.Equals(sourceDirNameFromFullPath, fileSystemSensitivity);
 
             // If the destination directories are the exact same name
-            if (!sameDirectoryDifferentCase
-                && string.Equals(sourcePath, destPath, fileSystemSensitivity))
+            if (!sameDirectoryDifferentCase && string.Equals(sourcePath, destPath, fileSystemSensitivity))
                 throw new IOException(SR.IO_SourceDestMustBeDifferent);
 
-            string? sourceRoot = Path.GetPathRoot(sourcePath);
-            string? destinationRoot = Path.GetPathRoot(destPath);
+            ReadOnlySpan<char> sourceRoot = Path.GetPathRoot(sourcePath.AsSpan());
+            ReadOnlySpan<char> destinationRoot = Path.GetPathRoot(destPath.AsSpan());
 
             // Compare paths for the same, skip this step if we already know the paths are identical.
-            if (!string.Equals(sourceRoot, destinationRoot, StringComparison.OrdinalIgnoreCase))
+            if (!sourceRoot.Equals(destinationRoot, StringComparison.OrdinalIgnoreCase))
                 throw new IOException(SR.IO_SourceDestMustHaveSameRoot);
 
             // Windows will throw if the source file/directory doesn't exist, we preemptively check
index c6a7791..87be8fe 100644 (file)
@@ -37,7 +37,7 @@ namespace System.IO
                     // FileNotFound only if the containing directory exists.
 
                     bool isDirectory = (error.Error == Interop.Error.ENOENT) &&
-                        (overwrite || !DirectoryExists(Path.GetDirectoryName(Path.TrimEndingDirectorySeparator(destFullPath))!));
+                        (overwrite || !DirectoryExists(Path.GetDirectoryName(Path.TrimEndingDirectorySeparator(destFullPath.AsSpan()))!));
 
                     Interop.CheckIo(
                         error.Error,
@@ -288,10 +288,9 @@ namespace System.IO
                 int i = length - 1;
                 while (i >= lengthRoot && !somepathexists)
                 {
-                    string dir = fullPath.Substring(0, i + 1);
-                    if (!DirectoryExists(dir)) // Create only the ones missing
+                    if (!DirectoryExists(fullPath.AsSpan(0, i + 1))) // Create only the ones missing
                     {
-                        stackDir.Push(dir);
+                        stackDir.Push(fullPath.Substring(0, i + 1));
                     }
                     else
                     {
@@ -309,7 +308,7 @@ namespace System.IO
             int count = stackDir.Count;
             if (count == 0 && !somepathexists)
             {
-                string? root = Path.GetPathRoot(fullPath);
+                ReadOnlySpan<char> root = Path.GetPathRoot(fullPath.AsSpan());
                 if (!DirectoryExists(root))
                 {
                     throw Interop.GetExceptionForIoErrno(Interop.Error.ENOENT.Info(), fullPath, isDirectory: true);