Skip to content

Change FSDirectory.Open() defaults to match .NET-specific platform and performance concerns #1301

Description

@NightOwl888

Is there an existing issue for this?

  • I have searched the existing issues

Task description

The FSDirectory.Open() method contains some business logic to select the best FSDirectory implementation for the current platform.

/// <summary>
/// Just like <see cref="Open(DirectoryInfo)"/>, but allows you to
/// also specify a custom <see cref="LockFactory"/>.
/// </summary>
public static FSDirectory Open(DirectoryInfo path, LockFactory lockFactory)
{
if ((Constants.WINDOWS || Constants.SUN_OS || Constants.LINUX) && Constants.RUNTIME_IS_64BIT /*&&
MMapDirectory.UNMAP_SUPPORTED*/) // LUCENENET specific - unmap hack not needed
{
return new MMapDirectory(path, lockFactory);
}
else if (Constants.WINDOWS)
{
return new SimpleFSDirectory(path, lockFactory);
}
else
{
return new NIOFSDirectory(path, lockFactory);
}
}

However, this business logic is based on what is the best option in Java. The 3 directory types may have very different performance characteristics in .NET due to a fundamentally different approach to providing random access and memory-mapped access to files.

We need to do some investigation based on performance profiles which directory option correctly maps to:

  • Specific operating systems
  • Runtime architecture (x64/x86/ARM64, etc.)
  • Target Framework

Note that this is currently blocked by #1267. We should do this investigation based on the new implementation.

AOT Limitations

After researching AOT limitations (see #1278), we need to ensure that the MMapDirectory is never selected as the default option where dynamic code is not supported. The canonical way to do that is to check:

if (!System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported)
{
    // AOT is likely in use and dynamic features are disabled.
    // Fallback to standard FileStream IO or handle gracefully.
}

Although, we should add that check to the Constants class so it can be shared project-wide. We could fall back to NIOFSDirectory instead of SimpleFSDirectory if it performs better, but it will take some experimentation to make that determination.

Note that the API is not supported on .NET Framework or .NET Standard 2.0, but we can build an internal conditionally compiled stub that is hard coded to true for that case as was already done in J2N.

.NET Framework/.NET Standard 2.0 Limitations

The System.IO.RandomAccess class did not exist before .NET 6. As a result the NIOFSDirectory is not currently a good candidate for being the default on anything other than .NET Core.

There has been some discussion about possibly making a port of System.IO.RandomAccess (or even a cut down version to patch our needs), but until it is actually done we should not select this directory as the default on older TFMs than .NET Core. Note that NIOFSDirecotry only uses the Read(SafeFileHandle, Span<byte>, long) overload.

macOS

In Java, the NIOFSDirectory was chosen over MMapDirectory on macOS. I suspect that once #1278 is completed MMapDirectory will probably be the best option instead, but it will require testing to confirm.


I suspect there will be other concerns down the road on which directory is best on a given platform, but we can deal with those concerns as they become known. It might not hurt to have AI audit our configuration and make some suggestions, though.

Metadata

Metadata

Assignees

No one assigned

    Labels

    is:taskA chore to be done

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions