You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提升C#中批量获取文件SID与NTAccount的速度?

优化大量文件获取NTAccount和SID的性能方案

针对36万级文件获取所有者信息时的性能瓶颈,可通过以下几种优化方案大幅缩短耗时:

1. 合并重复的所有者获取操作

原代码两次调用GetOwner分别获取SID和NTAccount,实际上只需获取一次SID,再通过Translate方法转换为NTAccount,减少一次系统IO交互:

var directorySecurity = Directory.GetAccessControl(directoryPath);
var sid = directorySecurity.GetOwner(typeof(System.Security.Principal.SecurityIdentifier)) as System.Security.Principal.SecurityIdentifier;
if (sid != null)
{
    ownerSid = sid.Value;
    var ntAccount = sid.Translate(typeof(System.Security.Principal.NTAccount)) as System.Security.Principal.NTAccount;
    ownerName = ntAccount?.Value;
}

2. 缓存SID与NTAccount的映射关系

大量文件往往属于同一所有者,重复解析SID到账户名会浪费资源。用字典缓存已解析的映射,避免重复转换:

// 静态缓存,全局复用
private static readonly Dictionary<string, string> _sidAccountCache = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

// 处理单个文件时
var sid = directorySecurity.GetOwner(typeof(System.Security.Principal.SecurityIdentifier)) as System.Security.Principal.SecurityIdentifier;
if (sid != null)
{
    ownerSid = sid.Value;
    // 优先从缓存读取
    if (!_sidAccountCache.TryGetValue(ownerSid, out ownerName))
    {
        var ntAccount = sid.Translate(typeof(System.Security.Principal.NTAccount)) as System.Security.Principal.NTAccount;
        ownerName = ntAccount?.Value;
        _sidAccountCache[ownerSid] = ownerName;
    }
}

3. 仅获取必要的安全信息

默认Directory.GetAccessControl会读取全部安全数据(所有者、组、权限列表等),但我们只需要所有者信息,指定AccessControlSections.Owner可减少IO传输的数据量:

// 仅获取所有者相关的安全信息
var directorySecurity = Directory.GetAccessControl(directoryPath, AccessControlSections.Owner);

4. 并行处理文件列表

文件操作属于IO密集型任务,利用多核CPU并行处理可大幅压缩总耗时,注意控制并行度避免IO过载:

// 假设filePaths是待处理的文件路径列表
Parallel.ForEach(filePaths, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }, filePath =>
{
    // 这里放入单个文件的处理逻辑(包含上述优化)
});

5. 直接调用Win32 API替代托管方法

托管的Directory.GetAccessControl封装了额外的检查逻辑,直接调用Win32的GetNamedSecurityInfo可减少封装开销,适合超大量文件场景:

using System.Runtime.InteropServices;

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern uint GetNamedSecurityInfo(
    string pObjectName,
    SE_OBJECT_TYPE ObjectType,
    SECURITY_INFORMATION SecurityInfo,
    out IntPtr pSidOwner,
    out IntPtr pSidGroup,
    out IntPtr pDacl,
    out IntPtr pSacl,
    out IntPtr pSecurityDescriptor);

private enum SE_OBJECT_TYPE
{
    SE_FILE_OBJECT = 1
}

private enum SECURITY_INFORMATION
{
    OWNER_SECURITY_INFORMATION = 0x00000001
}

// 使用示例
uint result = GetNamedSecurityInfo(
    filePath,
    SE_OBJECT_TYPE.SE_FILE_OBJECT,
    SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION,
    out IntPtr sidPtr,
    out _, out _, out _, out _);

if (result == 0) // 调用成功
{
    var sid = new System.Security.Principal.SecurityIdentifier(sidPtr);
    ownerSid = sid.Value;
    // 结合缓存处理NTAccount转换
    Marshal.FreeHGlobal(sidPtr); // 释放非托管内存
}

以上方案可组合使用,建议优先采用前三种轻量优化,若性能仍不达标再尝试并行或Win32 API方案。

内容的提问来源于stack exchange,提问作者user23329034

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:32:11