在unix / win32上有效地计算日志/时间戳以进行日志记录

时间:2012-08-06 04:31:59

标签: c++ winapi unix logging timestamp

我的情况是在对我们的系统进行分析和分析之后,得出的结论是系统的记录组件是许多瓶颈之一占据总运行时间的约17% - 很多记录的东西。

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

我想知道有多少技术人员可以有效地制作时间戳。

欢迎跨平台解决方案。

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

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

3 个答案:

答案 0 :(得分:3)

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

如果失败,优化将取决于您需要的分辨率。 我会问你是否绝对需要时间戳记日志,或者是否有序列信息的偶然时间戳可能有用?

示例:

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

我看到它的方式,你有两个问题:

  1. 将时间戳与其他系统同步
  2. 在单个系统上获取准确的时间戳
  3. 我会使用基于计时器的系统每毫秒更新时间戳两次,并在更新之间重新使用它。然后我会确保运行代码的系统将其时钟与原子钟同步。您生成时间戳两次,以尝试并补偿底层操作系统的计时器机制的瑕疵。

    我认为你不会比那更好。

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

    更新2:如果BOOST不适合,如果你不能使用C ++ 11,那么归结为:

    1. 使用计时器每毫秒设置两次时间戳并设置格式 - 您可以通过操作系统级API执行此操作。
    2. 确保按照进入的顺序记录事件。
    3. 假设I / O不是你的瓶颈,那么你的问题就是快速字符串连接。

答案 1 :(得分:0)

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

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

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

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

答案 2 :(得分:-1)

编辑:现在有多个downvoters。请发表评论,以便我能妥善解决问题。谢谢!

您可以重新组织代码,以便您的记录器从缓冲区读取日期时间戳字符串,该缓冲区由其他一些线程更新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在Windows上建议QueryPerformanceTimer,在Linux(和POSIX)上建议clock_gettime。但是,如果这些实现的高估仍然很高,则可以使用内联汇编直接查询处理器上的时间戳计数器(有关x86,请参阅rdtsc)。亚秒值是从结构中记录的值开始的delta'd,以获得适当的偏移量。

如果您能够以二进制格式记录时间戳,那么这将远离格式化问题。