在 StreamSink
類中,成員變量 _write_occurred
的作用是 跟蹤自上次刷新(Flush)以來是否有寫入操作發生,其核心目的是 優化 I/O 性能。以下是詳細解析:
_write_occurred
的作用
1. 避免不必要的刷新(Flush)
- 機制:
當write_log
方法(日志寫入)被調用時,_write_occurred
會被設為true
;
當flush_sink
方法(主動刷新)被調用時,僅在_write_occurred
為true
時執行實際的fflush
操作,隨后將其重置為false
。 - 優化意義:
避免在無新日志寫入時頻繁調用fflush
(系統調用),減少 I/O 開銷。
2. 狀態跟蹤
- 寫入標記:
記錄自上次刷新后是否有新數據寫入緩沖區。若未寫入,跳過刷新操作。 - 示例場景:
若連續多次調用flush_sink
但無新日志寫入,只有第一次會真正執行fflush
。
代碼流程解析
寫入日志時
void write_log(..., std::string_view log_statement) override {// ... 寫入日志到文件safe_fwrite(...); // 實際寫入操作_write_occurred = true; // 標記有寫入發生
}
- 寫入后必標記:無論日志內容是否為空,只要調用
write_log
即標記為true
。
主動刷新時
void flush_sink() override {if (!_write_occurred || !_file) { return; // 無寫入或文件未打開時直接返回}flush(); // 執行實際刷新
}void flush() {_write_occurred = false; // 重置標記fflush(_file); // 系統調用刷新緩沖區
}
- 條件刷新:僅在確實有寫入時調用
fflush
,避免無意義刷新。
設計必要性
性能優化
場景 | 無 _write_occurred | 有 _write_occurred |
---|---|---|
高頻寫入 | 每次 flush 觸發 fflush ,I/O 壓力大 | 僅在必要時觸發 fflush ,減少系統調用 |
低頻寫入 | 多余的 fflush 浪費 CPU 周期 | 無寫入時跳過 fflush ,節省資源 |
資源保護
- 文件句柄有效性:
若文件被意外關閉(如_file
變為nullptr
),flush_sink
會直接返回,避免操作無效指針。
典型應用場景
1. 日志批量寫入
// 連續寫入多條日志
sink.write_log(...); // _write_occurred = true
sink.write_log(...); // _write_occurred = true
sink.flush_sink(); // 實際刷新,重置 _write_occurred = false
sink.flush_sink(); // 直接返回(無新寫入)
2. 定時刷新策略
// 定時器每 1 秒觸發刷新
void on_timer() {sink.flush_sink(); // 僅當 1 秒內有新寫入時刷新
}
擴展:fflush
的成本
- 系統調用開銷:
fflush
會觸發用戶態到內核態的上下文切換,頻繁調用可能成為性能瓶頸。 - 磁盤 I/O 延遲:
強制將緩沖區數據寫入磁盤,涉及物理寫操作,延遲較高。 - 優化平衡:
通過_write_occurred
減少fflush
次數,在 數據安全性(及時持久化)和 性能 之間取得平衡。
總結
_write_occurred
是一個輕量級的狀態標志,通過簡單的布爾值跟蹤寫入狀態,實現了:
- 減少冗余 I/O 操作:避免無數據時的無效刷新。
- 降低系統調用開銷:提升高吞吐場景下的性能。
- 保護資源:防止操作無效文件指針。
它是高性能日志庫中常見的優化手段之一,尤其適用于需要平衡實時性和吞吐量的場景。
感觸:對于一些好的三方庫,還是有很多值得我們學習借鑒的知識點的,需要我們多想多思考多問一個為什么
【技術人的鼓勵】?? 如果這篇文章對您有幫助,歡迎點擊打賞按鈕支持博主!您的鼓勵是我持續輸出優質技術內容的動力,哪怕只是1元也足以讓我感受到這份珍貴的認可。💰