通过网络读取和解析大型文本文件的最佳方法是什么?

时间:2008-09-26 00:10:36

标签: c# .net multithreading parsing networking

我遇到一个问题,需要我从远程计算机解析几个日志文件。 有一些并发症: 1)该文件可能正在使用中 2)文件可能很大(100mb +) 3)每个条目可以是多行

要解决使用中的问题,我需要先复制它。我目前正在将它直接从远程计算机复制到本地计算机,并在那里进行解析。这导致了问题2.由于文件很大,在本地复制它可能需要很长时间。

为了增强解析时间,我想使解析器具有多线程,但这使得处理多行条目变得有点棘手。

两个主要问题是: 1)如何加快文件传输速度(压缩?,本地传输甚至是必要的?,我可以通过其他方式读取使用文件吗?) 2)在线程之间分割线时如何处理多行条目?

更新:我没有对服务器进行明显解析的原因是我希望尽可能减少对cpu的影响。我不想影响系统测试的性能。

9 个答案:

答案 0 :(得分:2)

如果您正在阅读顺序文件,则需要通过网络逐行阅读。您需要一种能够流式传输的传输方法。您需要检查您的IO流技术以解决这个问题。

像这样的大型IO操作不会受到多线程的好处,因为你可以像在网络上读取它们一样快地处理这些项目。

另一个很好的选择是将日志解析器放在服务器上,然后下载结果。

答案 1 :(得分:1)

考虑到您已经在复制文件的最简单方法是在复制之前压缩它,并在复制完成后解压缩。压缩文本文件会获得巨大的收益,因为zip算法通常可以很好地处理它们。此外,您现有的解析逻辑可以保持完整,而不必将其连接到远程网络文本阅读器。

这种方法的缺点是你无法非常有效地获得逐行更新,这对日志解析器来说是件好事。

答案 2 :(得分:1)

我想这取决于它的“远程”程度。 100Mb局域网上的100MB将大约8秒......将其增加到千兆位,你可以在大约1秒内完成它。这些卡需要50美元* 2,交换机需要100美元才能进行非常便宜的升级。

但是,假设它比那更远,你应该能够以只读模式打开它(当你复制时你正在读它)。 SMB / CIFS支持文件块读取,所以你应该在那时流式传输文件(当然,你实际上没有说你是如何访问文件的 - 我只是假设SMB)。

多线程无济于事,因为无论如何你都会受到磁盘或网络限制。

答案 3 :(得分:1)

使用压缩进行传输。

如果你的解析真的让你失望,并且你有多个处理器,你可以打破解析工作,你只需要以聪明的方式做 - 有一个确定的算法,工人负责处理记录不完整。例如,假设您可以确定一条线是记录中间的一部分,您可以将文件分成N / M段,每段都负责M行;当其中一个作业确定其记录未完成时,它必须继续读取,直到它到达记录的末尾。当其中一个作业确定它正在读取一个没有开头的记录时,它应该跳过该记录。

答案 4 :(得分:1)

从性能的角度来看,更好的选择是在远程服务器上执行解析。除了特殊情况之外,网络速度始终是瓶颈,因此限制通过网络发送的数据量将大大提高性能。

这是许多数据库使用在服务器端运行的存储过程的原因之一。

通过使用多线程解析速度(如果有的话)的改进将会被网络传输的比较速度所淹没。

如果您承诺在解析文件之前传输文件,您可以考虑的一个选项是在进行文件传输时使用动态压缩。 例如,有可用的sftp服务器可以即时执行压缩。 在本地端,您可以使用libcurl之类的东西来进行传输的客户端,这也支持动态解压缩。

答案 5 :(得分:1)

如果您可以复制该文件,则可以阅读该文件。因此,首先无需复制它。

编辑:使用FileStream class更多地控制访问和共享模式。

new FileStream("logfile", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)

应该这样做。

答案 6 :(得分:0)

我已经使用SharpZipLib压缩大文件,然后再通过Internet传输它们。所以这是一个选择。

1)的另一个想法是创建一个在远程机器上运行并在那里进行解析的程序集。您可以使用.NET远程处理从本地计算机访问程序集。远程程序集需要是Windows服务或托管在IIS中。这样您就可以将日志文件的副本保存在同一台机器上,理论上处理它们的时间会更短。

答案 7 :(得分:0)

我认为使用压缩(deflate / gzip)会有所帮助

答案 8 :(得分:0)

给定的答案不能令我满意,也许我的答案会帮助其他人以为它不是超级复杂,否则多线程在这种情况下将无益。也许它不会使传输速度更快,但是根据您解析的复杂程度,它可能会使得解析/分析数据的速度更快。

这实际上取决于您解析的细节。您需要从日志文件中获取什么样的信息?这些信息是统计信息还是它们取决于多个日志消息? 您有几种选择:

  • 我想最容易同时解析多个文件,您将文件作为上下文,并且可以为每个文件创建一个线程
  • 前面提到的另一个选项是对网络通信使用压缩
  • 您还可以使用一个帮助程序,将日志文件分成几行,这是第一步,然后由多个线程处理这些行;这种依赖行的解析应该非常容易和快捷。

在这种情况下非常重要的是衡量您的实际瓶颈所在。如果您的瓶颈是网络,那么优化解析器将不会带来太多好处。如果解析器创建了许多相同种类的对象,则可以使用ObjectPool模式并创建具有多个线程的对象。尝试处理输入而不分配太多新字符串。解析器通常是使用很多string.Split等来编写的,这实际上并没有它所能做到的那么快。您可以通过检查即将到来的值来导航Stream,而无需读取完整的字符串并再次对其进行拆分,但可以在解析完成后直接填充所需的对象。

几乎总是可以进行优化,问题是您从中获得了多少投入以及您的方案有多关键。