Skip to content
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

Enhance FileSystemEnumerable to track depth recursion #43748

Closed
iSazonov opened this issue Oct 23, 2020 · 6 comments · Fixed by #48148
Closed

Enhance FileSystemEnumerable to track depth recursion #43748

iSazonov opened this issue Oct 23, 2020 · 6 comments · Fixed by #48148
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.IO
Milestone

Comments

@iSazonov
Copy link
Contributor

iSazonov commented Oct 23, 2020

Splitted from #1953

Background and Motivation

In PowerShell Core repo we are trying to migrate to FileSystemEnumerable. Prototype shows great performance improvements.

We need to implement Depth parameter for Get-ChildItem cmdlet (aka dir). The parameter limits a depth of recursion.

This cannot be achieved without creating new classes (based on FileSystemEnumerator and FileSystemEnumerable) and creating non-trivial code as it requires processing a directory tree. All this negates the benefits of this API.

Proposed API

namespace System.IO
{
    public class EnumerationOptions
    {
        /// <summary>
        /// Stop recursion if current depth exceeds the value.
        /// Default is int.MaxValue (no limit).
        /// </summary>
        public int MaxRecursionDepth { get; set; }  // New API
    }
}

Usage Examples

var options = new System.IO.EnumerationOptions
    {
         RecurseSubdirectories = recurse,
         MatchType = MatchType.Win32,
         AttributesToSkip = 0,
         IgnoreInaccessible = false,
         MaxRecursionDepth = 2
    };

var paths = new FileSystemProviderEnumerable<string>(
                directory,
                (ref FileSystemEntry entry) => entry.FileName.ToString()),
                options)
    {
        ShouldIncludePredicate = FileSystemEntryFilter,

        ShouldRecursePredicate = (ref FileSystemEntry entry) => FileSystemRecursionPredicate
    };

Alternative Designs

What is better name - MaxRecursionDepth vs MaxDepthRecursion vs MaxDepthOfRecursion vs MaxDepth ?
(there is JsonSerializerOptions.MaxDepth)

Risks

Minor performance regression due to we have to keep additional uint value in a subdirectory queue.

Implementation details

Current implementation uses Queue to track subdirectories. We could put in the queue current depth +1 value together with subdirectory path. This allow to restore correct depth value at subdirectory dequeue.
And we need add Depth check in recursion condition.

@iSazonov iSazonov added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Oct 23, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.IO untriaged New issue has not been triaged by the area owner labels Oct 23, 2020
@jozkee
Copy link
Member

jozkee commented Oct 23, 2020

  • Should there be a value to specify "no limit"?
    • if the type were int then -1 could mean that (and throw on any other negative value).
  • For the sake of naming discussion, there is a similar API called JsonSerializerOptions.MaxDepth.
  • Why default is uint.MaxValue? Perhaps it should be the "no limit" value to avoid breaking behaviors.

@jozkee jozkee removed the untriaged New issue has not been triaged by the area owner label Oct 23, 2020
@jozkee jozkee added this to the Future milestone Oct 23, 2020
@iSazonov
Copy link
Contributor Author

iSazonov commented Oct 24, 2020

Should there be a value to specify "no limit"?

  • if the type were int then -1 could mean that (and throw on any other negative value).

I believe we have no need to have "no limit" value:

  • it is already default behavior
  • only if users need to limit recursion depth they will set explicit value.

Also this complicates implementation without need. If we will have "no limit" value we will have to:

  • either check the value on every step
  • or convert the value to MaxValue.

If we compare with JsonSerializerOptions.MaxDepth the last has a real default = 64 but for recursion default is "no limit" that is MaxValue.

For the sake of naming discussion, there is a similar API called JsonSerializerOptions.MaxDepth.

I added this in OP.

Why default is uint.MaxValue? Perhaps it should be the "no limit" value to avoid breaking behaviors.

The value should be positive by definition - no need to check in implementation.

No breaking changes. On windows long path length is 32,767 characters so max recursion depth is about 16000 and this less then uint.MaxValue.

But I'd agree to follow common pattern if the pattern is int.

Future milestone

My request is for 6.0 milestone since this is useful for PowerSHell and I am ready to pull PR with the API.

@jozkee jozkee added api-ready-for-review API is ready for review, it is NOT ready for implementation and removed api-suggestion Early API idea and discussion, it is NOT ready for implementation labels Oct 30, 2020
@terrajobst terrajobst added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review API is ready for review, it is NOT ready for implementation labels Feb 4, 2021
@terrajobst
Copy link
Contributor

terrajobst commented Feb 4, 2021

Video

  • We should int
  • The default value should be int.MaxValue. It seems 0 should just mean don't recurse at all, rather than no limit.
namespace System.IO
{
    public partial class EnumerationOptions
    {
        public int MaxRecursionDepth { get; set; }
    }
}

@iSazonov
Copy link
Contributor Author

iSazonov commented Feb 5, 2021

It seems 0 should just mean don't recurse at all, rather than no limit.

Yes, really it is to return only current directory items.


The proposal was updated based on the review.

@iSazonov
Copy link
Contributor Author

iSazonov commented Feb 9, 2021

I am ready to pull PR if .Net team approves.
/cc @carlossanlop

@carlossanlop
Copy link
Member

I assigned this issue to you, @iSazonov . Thank you for your help! Looking forward to review the PR.

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Feb 11, 2021
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Mar 31, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Apr 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.IO
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants