返回题库

stdout 延迟输出

Stdout Latency Sink

专题
Systems & Architecture / 系统与架构
难度
L1
来源
MyntBit

题目详情

高频交易系统要求极低延迟,同步 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.