Skip to content

Conversation

@Yundi339
Copy link

@Yundi339 Yundi339 commented Jan 4, 2026

相关

#2225
我在排查磁盘健康寿命的时候,发现TrafficMonitor存在频繁写入磁盘的问题,虽然是30s写入一次,但是全量写入的机制,实际上不友好的。

提交目的

解决 history_traffic.dat 文件频繁写入问题,通过引入增量保存机制,在保持数据安全性的前提下,大幅减少磁盘I/O操作。

细节说明

1. 数据结构重构

(目的是减少代码的复杂度,不用每次都更新数组,直接链表进行维护)

  • 分离存储设计: 将流量记录分为两部分
    • m_today_traffic: 单独存储今天的记录(频繁更新)
    • m_history_traffics: 历史记录链表(按日期从大到小排序,较少更新)
    • m_traffics_cache: 缓存合并后的完整列表(按需更新)

2. 新增增量保存机制

(这是我加入的核心功能,可以有效减少磁盘写入频率,原先的全量保存是写一点就触发一次缓冲区同步,对磁盘IO来说是很不友好的)

  • 新增方法: SaveTodayOnly()
    • 只更新文件的前两行:
      1. 第一行:lines计数(今天的记录 + 历史记录数量)
      2. 第二行:今天的流量记录
    • 保留文件第3行及之后的历史记录,直接读取后写入,不进行格式化处理
    • 在日期改变或文件不存在时,自动降级为完整保存

3. 保存策略优化

(原本是30s && 100kB 触发一次保存,现在增加更大的30s&&10MB)

  • 频繁保存场景(流量变化超过10MB时):

    • 使用 SaveHistoryTraffic()SaveTodayOnly() 进行增量保存
    • 大幅减少I/O操作,只写入必要的数据
  • 程序退出/系统关机场景:

    • 使用 SaveHistoryTrafficFull()Save() 进行完整保存
    • 确保所有数据完整写入,保证数据安全

4. 缓存机制

(简化代码复杂度)

  • 引入 m_cache_dirty 标志,实现按需更新缓存
  • GetTraffics() 方法在缓存过期时自动更新
  • 避免频繁的列表合并操作

5. 数据一致性保障

(简化代码复杂度)

  • IsTodayRecord() 方法检查今天的记录日期是否正确
  • 日期改变时自动调用 OnDateChanged() 将今天的记录移到历史记录
  • MormalizeData() 方法确保数据排序和去重

影响分析

  1. 性能显著提升

    • I/O操作大幅减少: 从每次完整写入整个文件(可能包含数百条历史记录)改为只写入2行
    • 磁盘写入频率降低: 在频繁保存场景下,写入数据量减少90%以上
    • 响应速度提升: 减少文件I/O阻塞时间,提升程序响应性
  2. 磁盘寿命延长

    • 减少对SSD/HDD的写入磨损
    • 特别适用于长时间运行的场景
  3. 数据安全性保持

    • 程序退出时仍使用完整保存,确保数据完整性
    • 增量保存有完善的降级机制(日期改变、文件不存在时自动完整保存)
    • 备份机制保持不变

⚠️ 潜在风险与应对

  1. 文件格式兼容性

    • 风险: 新代码读取旧文件格式时可能出现问题
    • 应对: Load() 方法保持向后兼容,能正确解析旧格式文件
    • 影响: 无,向后兼容
  2. 并发访问

    • 风险: 如果多个进程同时访问文件,可能出现数据不一致
    • 应对: 单进程应用,不存在并发问题
    • 影响: 无
  3. 文件损坏恢复

    • 风险: 增量保存过程中程序异常退出,可能导致文件损坏
    • 应对:
      • 有备份机制(.bak文件)
      • 程序启动时会检查并尝试从备份恢复
      • 增量保存失败时会降级为完整保存
    • 影响: 低,有多重保障机制
  4. 数据丢失风险

    • 风险: 增量保存只更新前两行,如果历史记录被外部修改,可能丢失
    • 应对:
      • 历史记录部分直接读取后写入,不进行解析和格式化
      • 如果文件格式正确,不会丢失数据
    • 影响: 极低,正常情况下不会发生

@Yundi339
Copy link
Author

Yundi339 commented Jan 4, 2026

📊 性能对比(估算)

场景 旧方案 新方案 提升
单次保存数据量 全部记录(假设100条) 2行 减少98%
保存耗时 ~10-50ms ~1-5ms 减少80-90%
磁盘写入次数 每次完整写入 只写入必要部分 大幅减少

技术亮点

  1. 智能降级机制: 增量保存失败时自动降级为完整保存,保证可靠性
  2. 缓存优化: 使用脏标记实现按需更新,避免不必要的计算
  3. 数据分离: 将频繁更新的数据和静态数据分离,优化I/O模式
  4. 向后兼容: 保持文件格式兼容,不影响现有数据

@Yundi339
Copy link
Author

Yundi339 commented Jan 4, 2026

1、监控测试结果
这是一个微软的Process Monitor进程监控工具,优化后显示WriteFile事件,30秒内只触发几次写事件。
在之前,由于是全量写入,会导致每写1行数据就触发一次数据同步。
image

2、已测试+1天、备份、未来数据
补充:如果history_traffic.dat.bak、history_traffic.dat都包含未来的数据,在加载时会自动清理未来数据。
由于只更新前两行,我认为,只有人为制造这种异常数据,才会触发风险。不过我也还是在代码中,加上了日期排序,保证数据按照顺序记录。
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant