代码之家  ›  专栏  ›  技术社区  ›  Electro SoapBox

C++中的异步线程安全日志

  •  16
  • Electro SoapBox  · 技术社区  · 14 年前

    我正在寻找一种在C++项目中进行异步和线程安全日志记录的方法,如果可能的话,只需要一个文件。我正在使用 cerr clog 对于任务,但由于它们是同步的,所以每次记录某些内容时执行都会很快暂停。这是一个相对图形化重的应用程序,所以这类事情相当烦人。

    新的记录器应该使用异步I/O来消除这些暂停。线程安全也是可取的,因为我打算很快添加一些基本的多线程。

    我曾考虑过一个每个线程一个文件的方法,但这似乎会使管理日志成为一场噩梦。有什么建议吗?

    5 回复  |  直到 7 年前
        1
  •  19
  •   Kate Gregory    13 年前

    我注意到这条1年多的线。也许我写的异步日志程序可能会感兴趣。

    http://www.codeproject.com/KB/library/g2log.aspx

    g2log使用受保护的消息队列将日志条目转发给磁盘访问速度较慢的后台工作进程。

    我试过使用一个无锁队列,它增加了日志调用的平均时间,但减少了最坏情况下的时间,但是我现在使用的是受保护的队列,因为它是跨平台的。它在Windows/Visual Studio 2010和Ubuntu 11.10/GCC4.6上进行了测试。

    它作为公共域发布,因此您可以在不附加任何字符串的情况下使用它。

        2
  •  4
  •   Amardeep AC9MF    14 年前

    这是非常可能和实际的。我怎么知道?我上一份工作就是这么写的。不幸的是(对我们来说),他们现在拥有代码。:-)可悲的是,他们甚至不使用它。

    我打算在不久的将来编写一个开源版本。同时,我可以给你一些提示。

    1. I/O操纵器实际上只是函数名。您可以为自己的日志类实现它们,这样您的日志程序就可以兼容cout/cin了。
    2. 操纵器函数可以标记操作并将其存储到队列中。
    3. 一个线程可以被阻塞在队列上,等待大量的日志通过。然后它处理字符串操作并生成实际的日志。

    这本质上是线程兼容的,因为您使用的是队列。但是,您仍然希望在写入队列时放置一些类似互斥的保护,这样给定的日志<<“stufacture”<<“more stufacture”类型操作仍然是行原子操作。

    玩得高兴!

        3
  •  1
  •   Cubbi    14 年前

    我认为正确的方法不是每个线程一个文件,而是每个文件一个线程。如果系统中的任何一个文件(或一般资源)只被一个线程访问过,那么线程安全编程就变得容易多了。

    所以,为什么不让logger成为一个专用的线程(或者多个线程,每个文件一个,如果您在不同的文件中记录不同的东西),在所有其他线程中,写入日志会将消息放在适当的logger线程中的输入队列上,在写入之前的消息之后,该线程就会到达它。它只需要一个互斥量来保护队列在记录器读取事件时不添加事件,以及一个condvar来保护记录器在队列为空时等待。

        4
  •  1
  •   Matthieu M.    14 年前

    你考虑过使用日志库吗?

    我发现有几个是可以用的 Pantheios 最近,似乎真的很不可思议。

    它更像是一个前端记录器,您可以自定义使用哪个系统。它可以与 ACE log4cxx 例如,它看起来很容易使用和配置。它的主要优点是使用了类型安全操作符,这是非常好的。

    如果您只想要一个无骨日志库:

    • 王牌
    • Log4C*
    • 提升日志

    挑选任何一个)

    我应该注意到,在C++中实现无锁队列是可能的,并且它们对于日志记录非常有用。

        5
  •  0
  •   Jezor    7 年前

    我也有同样的问题,我相信我找到了完美的解决方案。我向您介绍了一个名为loguru的单头库: https://github.com/emilk/loguru

    它使用简单,可移植,可配置,基于宏,默认情况下不会 #include 任何东西(为了那甜蜜甜蜜的编纂时代)。