【问题标题】:Which is the most performance based method of writing logs for Application哪种是为应用程序编写日志的最基于性能的方法
【发布时间】:2023-03-21 21:20:01
【问题描述】:

我在一个客户端服务器应用程序中工作,其中多个客户端和服务器正在为性能非常关键的金融交易进行基于套接字的通信。目前我正在使用 system.IO 命名空间的 streamwriter 将日志写入文件。对于单个事务,我需要调用 streamwriter 方法 50 次以记录不同的值,对于超过 50,000 个事务,此记录所花费的时间变得非常重要。

如何减少应用程序进行日志记录的时间?我是否需要选择其他方法或任何其他类而不是streamwriter?用更短的时间进行日志记录的最佳方法是什么。

【问题讨论】:

  • 我相信大多数现代日志框架都在使用某种缓冲区。您是否尝试过使用其中一个(log4net 是我想到的第一个)?
  • 嗨史蒂夫。到目前为止,我还没有尝试过 log4net,也不太了解。您是否觉得在我当前的应用程序中使用它对我有好处
  • ...或 nLog(用一些非常高的输出日志很好地为我服务)
  • @AshishKhandelwal 绝对尝试现有的记录器之一。它们是由几个人多年来开发的,旨在提供具有多种选择的高性能。它们在保持输出顺序的同时利用缓冲区、线程等。我建议您不要在不先尝试其中一个的情况下自行推出,因为可能会有陷阱。我没有使用过 NLog,但使用 Log4Net 已经 没有任何抱怨。
  • 以下是在决定您的日志记录策略时需要考虑的一些一般事项。 sometechfacts.blogspot.com/2018/04/…

标签: c# .net logging streamwriter


【解决方案1】:

在将值写入磁盘之前缓存它们。

仅在您完成事务后提交日志。

类似这样的:

StringBuilder builder = new StringBuilder();
// do transaction step 1
builder.Append("Transaction step 1" + environment.NewLine); // or however you add a line to you log

// step 2
builder.Append("Transaction step 2" + environment.NewLine);

//...

// step 50
builder.Append("Transaction step 50" + environment.NewLine);

// now write to the file
File.WriteAllText(@"C:\log.txt", builder.ToString());

如果在任何步骤中出现错误,您可以添加一些处理以仍然写入日志。

您还可以使用一些开源工具,例如 log4net:http://logging.apache.org/log4net/

【讨论】:

  • 这将取决于是否存在“交易”的概念。如果缓冲区不断被写入......需要一个“刷新阈值”。
  • 在金融应用程序中,您通常处理一些事务,即处理一些记录。处理记录后,任何处理都可以通过提交顺序完成。或者正如您所说,您需要每 X 秒刷新一次缓冲区。
  • 我的意思是,如果你将这个概念引入到日志中,那么你就会被它所束缚。如果您将何时刷新的决定留给日志记录机制,则您不会被绑定到事务。希望这是有道理的:)
  • 请不要建议将字符串连接50次!
  • 对不起,最好写一个文件 50 次?我想你的意思是字符串构建是使用字符串构建器。
【解决方案2】:

我建议登录数据库(高性能,可能嵌入 sqlite/sqlce)。奖励 - 您可以构建和查询您的日志条目。

【讨论】:

    【解决方案3】:

    我建议你试试 Log4Net,你可以配置 where (file, database, xml) 和 when (bath, transaction, ...) 并轻松切换跟踪级别 (debug, info, warning, ...)

    从头开始编写日志系统是不值得的。

    【讨论】:

      【解决方案4】:

      为了减少记录所花费的时间,我建议:

      • 确保记录的数据需要最少的转换/格式化
      • 创建或使用一个日志库:
        • 当被调用时,将记录数据(连同要记录的时间、线程 ID 和其他标记)放在缓冲区中。
        • 定期将缓冲数据刷新到磁盘(即当缓冲数据大到足以填满日志文件中的至少一个物理块时立即刷新,或在系统空闲时立即刷新,或每隔 x 秒定期刷新)。
        • 锁定日志文件以进行独占写入访问,因此您可以在软件运行时查看它,但其他进程无法将其锁定在您的脚下。
        • 使用单独的线程来处理刷新,即不要减慢您的工作线程。
      • 如果您有许多服务器进程,请考虑使用 IPC 将日志数据发送到一个点,以最大限度地减少正在写入的活动文件数量和正在使用的缓冲区数量(您可能需要进行测试,看看这是否值得它,并且您可能必须添加标签以显示每个条目的来源)。
      • 对日志进行计划/空闲时间备份,以防止它们变得太大。

      【讨论】:

        【解决方案5】:

        如果性能是关键,那么我会考虑查看 Windows 事件跟踪 (AKA ETW)。

        借助 .NET 4.5 和 EventSource 类的引入,这使得 ETW 比过去更容易实现。

        Vance Morrison's Weblog 有一些关于这个主题的好文章。

        有关架构的概述,请参阅Improve Debugging And Performance Tuning With ETW

        还有来自 Microsoft 模式和实践团队的 Semantic Application Block,它可以更轻松地整合 EventSource 功能和管理日志记录行为。

        【讨论】:

        • ETW +1。像往常一样,大多数答案都表明对那里有什么以及它有多好一无所知。 kernetl 中提供的基础设施难以超越。
        • 谢谢,@TomTom,我认为 ETW 并没有真正“提升”得很好,以前它对于典型的业务线应用程序来说相当复杂。随着 .NET 4.5 的添加,我认为它会吸引更多的追随者。
        • 我非常希望。很难打败。仍然有一些“未解决的问题”(仍在寻找一种将 ETW 轻松移动到 Windows 日志中的方法),但它确实具有很好的功能。
        • @TomTom,您可能有兴趣查看新的语义应用程序块 CTP(请参阅答案)。
        【解决方案6】:

        提高应用程序性能并能够写出所有这些日志消息的一种方法是将它们排队到 MSMQ 队列中,并让 Windows 服务应用程序在服务器未加载时处理排队的日志消息。您也可以将队列放在完全独立的服务器上。

        在实现方面,您可以设置使用 MSMQ 处理日志消息的 WCF Web 服务。这比必须设置 Windows 服务更容易。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-10-30
          • 2010-12-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-19
          相关资源
          最近更新 更多