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

.NET Core读取文件内存上涨,如何每次读取后释放内存?

解决.NET Core读取文件时内存持续增长的问题

你的问题核心在于一次性将所有日志对象加载到内存中的List集合里,如果日志文件较大,每次调用都会在内存中堆积大量对象,GC无法及时回收就会导致内存持续上涨。下面是针对性的优化方案:

核心优化:改用流式返回(推荐)

把返回类型从List<LogResult>改为IEnumerable<LogResult>,通过yield return实现延迟加载,每次只处理一行数据,不会在内存中缓存所有日志对象,从根源上解决内存累积问题:

public IEnumerable<LogResult> GetData()
{
    // 复用序列化配置,减少重复创建的开销
    var jsonOptions = new JsonSerializerOptions();
    
    using (StreamReader sr = new StreamReader("logs\\logsCopy.log"))
    {
        string line;
        while ((line = sr.ReadLine()) != null)
        {
            if (string.IsNullOrWhiteSpace(line))
                continue;
            
            // 先判断字符串长度,避免索引越界
            if (line.Length <= 1)
                continue;
                
            var cleanedLine = line.Remove(line.Length - 1, 1);
            var log = JsonSerializer.Deserialize<LogResult>(cleanedLine, jsonOptions);
            
            if (log != null)
                yield return log.UnescapeMessage(); // 直接返回处理后的单条数据
        }
    }
}

额外优化点

  • 避免不必要的字符串分配:原代码中line.Remove会创建新字符串,如果日志行末尾的字符是固定的(比如多余的逗号),可以直接用line.Substring(0, line.Length - 1),效果一致但语义更清晰。
  • 复用JsonSerializerOptions:每次调用Deserialize时重复创建配置对象会增加内存开销,提前创建并复用能减少不必要的内存分配。
  • 检查UnescapeMessage扩展方法:如果这个方法内部有静态缓存或者没有及时释放资源,也可能导致内存泄漏,确保它的实现是无状态且不会累积数据的。

如果必须返回List的情况

如果业务逻辑要求必须返回List,那要确保每次调用后List能被GC及时回收,同时可以限制单次读取的数量,或者分批处理,但这种方式依然会占用较多内存,不如流式返回高效:

public List<LogResult> GetData()
{
    var result = new List<LogResult>();
    var jsonOptions = new JsonSerializerOptions();
    
    using (StreamReader sr = new StreamReader("logs\\logsCopy.log"))
    {
        string line;
        while ((line = sr.ReadLine()) != null)
        {
            if (string.IsNullOrWhiteSpace(line) || line.Length <= 1)
                continue;
                
            var cleanedLine = line.Substring(0, line.Length - 1);
            var log = JsonSerializer.Deserialize<LogResult>(cleanedLine, jsonOptions);
            
            if (log != null)
                result.Add(log.UnescapeMessage());
        }
    }
    
    return result;
}

这种情况下,要确保调用方使用完List后不会持有引用,让GC能及时回收内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 08:52:45