5

我的情况是,在对我们的系统进行分析和分析后,得出的结论是,系统的日志记录组件是占用总运行时间约 17% 的众多瓶颈之一 - 记录了很多事情.

其中,记录器消耗的大约 5% 的时间与生成以下格式的 ascii 日期/时间戳有关:YYYYMMDD HHMMSS.fff - 我们大约每秒记录约 700k 行。(大约 700K x (localtime and gettimeofday) 每秒调用)

我想知道 SOers 有什么技术可以有效地生成时间戳。

跨平台解决方案将受到欢迎。

注 1:我们研究了 Boost.datetime - 它很棒,但是对于我们的需求来说有点太慢了,std::chrono 是一个完美的解决方案,但是不幸的是我们必须支持 pre c++11 编译器。

注意 2:我们已经实现了一个简单的优化,它每 24 小时只计算一个日期部分 (yyyymmdd),因此每行只有 1 个 gettimeofday 调用 - 但没有多大帮助。

4

3 回答 3

3

如果您可以选择使用 C++11,您应该查看std::chrono

如果做不到这一点,优化将取决于您需要的分辨率。我会问您是否绝对需要日志记录时间戳,或者带有序列信息的偶尔时间戳是否有用?

例子:

<timestamp1> <seq_num_0> ...
<timestamp1> <seq_num_1> ...
....
<timestamp1> <seq_num_n-1> ...
<timestamp2> <seq_num_0> ...

在我看来,你有两个问题:

  1. 与其他系统同步时间戳
  2. 在单个系统上获取准确的时间戳

我会使用基于计时器的系统每毫秒更新两次时间戳,并在更新之间重新使用它。然后,我会确保运行您的代码的系统的时钟与原子钟同步。您生成两次时间戳以尝试补偿底层操作系统计时器机制的脆弱性。

我不认为你能得到比这更好的了。

编辑:实际上,你可以。确保仅在时间戳字符串更改时对其进行格式化。你也不需要序列号,如果你能保证条目按照它们进入的顺序被记录。鉴于这两个假设,你的日志记录问题现在减少到你可以连接和写出两个字符串的速度。

更新 2:如果 BOOST 不适合并且您不能使用 C++11,则归结为:

  1. 使用计时器每毫秒设置和格式化两次时间戳 - 您可以通过操作系统级别的 API 执行此操作。
  2. 确保事件按照它们进入的顺序记录。

假设 I/O 不是您的瓶颈,那么您的问题就是快速字符串连接之一。

于 2012-08-06T04:41:59.913 回答
0

我会延迟任何和所有格式,直到实际需要:

struct log_entry {
    struct timeval timestamp;
    unsigned int code;
    union {
        struct param1 p1;
        struct param2 p2;
    };
};

这些paramN结构以当时的任何形式包含适合事件的数据,但作为副本(因此可以单独分析日志数据)。

根据您的要求,您可以将此数据保存在环形缓冲区中,并不断覆盖旧数据,或者在达到一定百分比时将其转储到磁盘。

于 2012-08-06T06:44:18.183 回答
-1

编辑:现在有多个反对者。请发表评论,以便我可以正确解决问题。谢谢!

您可以重新组织您的代码,以便您的记录器从缓冲区读取日期时间戳字符串,该缓冲区由其他线程每秒更新 N 次(取决于您所需的分辨率)。每秒 4 次:

struct current_time_stamp {
    char timestr_[4][16];
    unsigned index_;
    unsigned subsecond_;
    const char *get () const { return timestr_[index_%4]; }
    void update () {
        // ... update string in timestr_[(index_+1)%4] ...
        // ... if (index_ + 1)%4 is zero, recompute subsecond_
        ATOMIC_INCREMENT(index_);
        // ... also need a memory barrier for timestr_ update
    }
};

每个日志的亚秒级分辨率将从高性能计数器读取。DeadMG 建议QueryPerformanceTimer在 Windows 上,在 Linux(和 POSIX)上有clock_gettime. 但是,如果这些实现的开销对您来说仍然很高,您可以使用内联汇编直接查询处理器上的时间戳计数器(参见rdtscx86)。亚秒级值与结构中记录的值相加,以获得正确的偏移量。

如果您可以摆脱以二进制格式记录时间戳,那将摆脱格式问题。

于 2012-08-06T06:20:21.500 回答