Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Tracking FileSystem provider performance issues #14497

Copy link
Copy link
@iSazonov

Description

@iSazonov
Issue body actions
  1. The IsPathRoot() method does double check for UNC
    /// <summary>
    /// Determines if the specified path is either a drive root or a UNC root.
    /// </summary>
    /// <param name="path">
    /// The path
    /// </param>
    /// <returns>
    /// True if the path is either a drive root or a UNC root, or false otherwise.
    /// </returns>
    private static bool IsPathRoot(string path)
    {
    if (string.IsNullOrEmpty(path))
    {
    return false;
    }
    bool isDriveRoot = string.Equals(path, Path.GetPathRoot(path), StringComparison.OrdinalIgnoreCase);
    bool isUNCRoot = IsUNCRoot(path);
    bool result = isDriveRoot || isUNCRoot;
    s_tracer.WriteLine("result = {0}; isDriveRoot = {1}; isUNCRoot = {2}", result, isDriveRoot, isUNCRoot);
    return result;
    }

    and could be replaced with more short and fast code. Proposal from @mklement0 Tracking FileSystem provider performance issues #14497 (comment)

Also we need to review GetFileSystemItem(string path, ref bool isContainer, bool showHidden) - there is a root check and maybe a bug (no UNC share check)

bool isRootPath =
string.Equals(
Path.GetPathRoot(path),
result.FullName,
StringComparison.OrdinalIgnoreCase);

  1. PR Reduce aggressive correcting casing of file system paths #14469 Reduce aggressive correcting casing of file system paths
    On Windows we do case normalizations even if results are not used.

  2. No need to allocate FileInfo and extra strings in IsSameWindowsVolume():

    private static bool IsSameWindowsVolume(string source, string destination)
    {
    FileInfo src = new FileInfo(source);
    FileInfo dest = new FileInfo(destination);
    return (src.Directory.Root.Name == dest.Directory.Root.Name);
    }

    We can use GetDirectoryName(ReadOnlySpan<char> path). Also we should use Ordinal comparison.

  3. EnsureDriveIsRooted() method does extra path.IndexOf(':') - we can simply check last char

    private static string EnsureDriveIsRooted(string path)
    {
    string result = path;
    // Find the drive separator
    int index = path.IndexOf(':');
    if (index != -1)
    {
    // if the drive separator is the end of the path, add
    // the root path separator back
    if (index + 1 == path.Length)
    {
    result = path + StringLiterals.DefaultPathSeparator;
    }
    }
    return result;
    }

  4. We need to review semantic of IsValidPath() method. If it is exactly about path validity the method could be simplified but we need to measure a performance. In common case it is impossible to validate path by parsing but only by opening.

    protected override bool IsValidPath(string path)
    {
    // Path passed should be fully qualified path.
    if (string.IsNullOrEmpty(path))
    {
    return false;
    }
    // Normalize the path
    path = NormalizePath(path);
    path = EnsureDriveIsRooted(path);
    #if !UNIX
    // Remove alternate data stream references
    // See if they've used the inline stream syntax. They have more than one colon.
    int firstColon = path.IndexOf(':');
    int secondColon = path.IndexOf(':', firstColon + 1);
    if (secondColon > 0)
    {
    path = path.Substring(0, secondColon);
    }
    #endif
    // Make sure the path is either drive rooted or UNC Path
    if (!IsAbsolutePath(path) && !Utils.PathIsUnc(path))
    {
    return false;
    }
    // Exceptions should only deal with exceptional circumstances,
    // but unfortunately, FileInfo offers no Try() methods that
    // let us check if we _could_ open the file.
    try
    {
    FileInfo testFile = new FileInfo(path);
    }
    catch (Exception e)
    {
    if ((e is ArgumentNullException) ||
    (e is ArgumentException) ||
    (e is System.Security.SecurityException) ||
    (e is UnauthorizedAccessException) ||
    (e is PathTooLongException) ||
    (e is NotSupportedException))
    {
    return false;
    }
    else
    {
    throw;
    }
    }
    return true;
    }

  5. Statistic shows:

dir -Recurse 'C:\Program Files (x86)\' | Select -ExpandProperty Mode | Sort-Object  | Group-Object -NoElement

Count Name
----- ----
    1 -----
    3 --r--
44263 -a---
    6 -ar--
 8136 d----
    3 d---s
    2 d-r--
 1044 la---

and we could add "la---" as a static element in

if (!isLink)
{
// special casing for the common cases - no allocations
switch (fileAttributes)
{
case FileAttributes.Archive:
return "-a---";
case FileAttributes.Directory:
return "d----";
case FileAttributes.Normal:
return "-----";
case FileAttributes.Directory | FileAttributes.ReadOnly:
return "d-r--";
case FileAttributes.Archive | FileAttributes.ReadOnly:
return "-ar--";
}
}

                if (!isLink)
                {
                    // special casing for the common cases - no allocations
                    switch (fileAttributes)
                    {
                        case FileAttributes.Archive:
                            return "-a---";
                        case FileAttributes.Directory:
                            return "d----";
                        case FileAttributes.Normal:
                            return "-----";
                        case FileAttributes.Directory | FileAttributes.ReadOnly:
                            return "d-r--";
                        case FileAttributes.Archive | FileAttributes.ReadOnly:
                            return "-ar--";
                    }
                }
                else if (fileAttributes == FileAttributes.ReadOnly)
                {
                    return "la---";
                }

           ...
  1. Remove double check ItemExists();
    private void CopyAndDelete(DirectoryInfo directory, string destination, bool force)
    {
    if (!ItemExists(destination))
    {
    CreateDirectory(destination, false);
    }
    else if (ItemExists(destination) && !IsItemContainer(destination))
    {
Reactions are currently unavailable

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Enhancementthe issue is more of a feature request than a bugthe issue is more of a feature request than a bugWG-Engine-Performancecore PowerShell engine, interpreter, and runtime performancecore PowerShell engine, interpreter, and runtime performance

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.