.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
相关产品推荐
相关产品推荐

