stdout 延迟输出
Stdout Latency Sink
题目详情
高频交易系统要求极低延迟,同步 I/O 操作如日志写入会成为瓶颈。为此,日志消息通常先在内存中缓冲,再异步刷新,将时间关键的日志操作与较慢的格式化和写入过程分离。
任务:实现 LatencyLogger 类,高效缓冲和格式化日志消息。log() 方法将消息存入环形缓冲区(O(1) 操作),后台线程定期将缓冲区内容格式化并写入 stdout。支持多线程并发调用 log()。
英文原题
High-frequency trading systems require minimal latency, making synchronous I/O operations like logging a significant bottleneck. To mitigate this, log messages are often buffered in memory and flushed asynchronously, separating the time-critical logging operation from the slower formatting and writing process.
Task
Implement the LatencyLogger class to buffer and format log messages efficiently. The class must provide the following public interface:
- A constructor LatencyLogger(std::function<lo
解析
问题分析
延迟测量需要一个低开销的输出通道。写入 stdout 比写入文件或网络通常更快(缓冲输出),但也可能受终端速度影响。写入 /dev/null 可测量纯序列化开销作为基线。
实现
class LatencySink {
std::vector<std::chrono::nanoseconds> samples_;
FILE* out_;
public:
explicit LatencySink(const char* path = "/dev/null") : out_(fopen(path, "w")) {}
void record(std::chrono::nanoseconds lat) {
samples_.push_back(lat);
if (samples_.size() >= 100000) flush();
}
void flush() {
for (auto s : samples_) fprintf(out_, "%ld\n", (long)s.count());
fflush(out_); samples_.clear();
}
~LatencySink() { flush(); fclose(out_); }
};复杂度与边界
- 时间复杂度:record O(1) 均摊,flush O(N)
- 空间复杂度:O(批量大小)
- 边界条件:(1) 批量写入减少系统调用 (2) SIGPIPE 可能导致进程终止 (3) 需异步或离线分析样本
英文解析
Analysis
Latency measurement requires a low-overhead output channel. Writing to stdout is typically faster than writing to files or network (buffered output), though terminal speed may affect it. Writing to /dev/null measures pure serialization overhead as a baseline.
Solution
class LatencySink {
std::vector<std::chrono::nanoseconds> samples_;
FILE* out_;
public:
explicit LatencySink(const char* path = "/dev/null") : out_(fopen(path, "w")) {}
void record(std::chrono::nanoseconds lat) {
samples_.push_back(lat);
if (samples_.size() >= 100000) flush();
}
void flush() {
for (auto s : samples_) fprintf(out_, "%ld\n", (long)s.count());
fflush(out_); samples_.clear();
}
~LatencySink() { flush(); fclose(out_); }
};Complexity & Edge Cases
- Time complexity: record O(1) amortized, flush O(N)
- Space complexity: O(batch size)
- Edge cases: (1) Batch writing reduces system call overhead (2) SIGPIPE may terminate the process (3) Samples require async or offline analysis
Verification
Record 1M latency samples to /dev/null, measure overhead per record. Benchmark against file-based sink. Verify batch flush reduces syscall count.
Key Considerations
Batched latency recording minimizes measurement overhead. In tick-to-trade latency measurement, every nanosecond of recording overhead adds bias. Using /dev/null as baseline and batched flush to disk for production ensures the measurement tool itself does not distort the results.