【问题标题】:Howto read this large text file? Memory Mapped File?如何阅读这个大文本文件?内存映射文件?
【发布时间】:2012-08-03 23:51:58
【问题描述】:

我正处于一个简单工具的设计阶段,我想在需要读取大型日志文件的地方编写。为了给你们一些背景信息,我将首先向你们解释一下。

我需要阅读的日志文件由日志条目组成,这些条目总是由以下 3 行格式组成:

statistics : <some data which is more of less of the same length about 100 chars>
request :  <some xml string which can be small (10KB) or big (25MB) and anything in between>
response :  <ditto>

日志文件的大小约为 100-600MB,这意味着大量的日志条目。现在这些日志条目可以相互关联,为此我需要从头到尾读取文件。这些关系可以从统计线推导出来。

我想使用统计行中的信息来构建一些数据网格,用户可以使用它来搜索数据并进行一些过滤操作。现在我不想将请求/响应行加载到内存中,直到用户真正需要它。此外,我想通过限制加载的请求/响应条目的最大值来保持较小的内存负载。

所以我认为当我第一次解析文件并创建统计索引时,我需要保存统计行的偏移量。然后,当用户单击某个作为日志条目元素的统计信息时,我使用此偏移量从文件中读取请求/响应。然后我可以为它保留一些内存池,以确保没有太多加载的请求/响应条目(请参阅前面的请求)。

问题是我不知道用户多久需要一次请求/响应数据。可能很多,也可能是几次。此外,日志文件可以从网络共享加载。

我的问题是:

  1. 这是因为可能存在大量读取操作而应该使用内存映射文件的情况吗?还是使用普通文件流更好。顺便提一句。在这个阶段我不需要对日志文件进行写入操作,但将来可能会这样做!

到目前为止,如果您有其他提示或发现我的想法存在缺陷,请告诉我。我愿意接受任何方法。

更新:

进一步澄清:

  • 当用户从驱动器或网络共享加载日志文件时,工具本身必须进行解析。

  • 该工具将被编写为 WinForms 应用程序。

  • 用户可以导出选定的日志条目。目前此导出的格式未知(二进制、文件 db、文本文件)。此导出可由应用程序本身导入,然后仅显示用户所做的选择。

【问题讨论】:

  • 旁注:你真的需要考虑你的目标是什么......到目前为止,你的问题是“我不知道我想要什么,但它足够快吗?”由于您将其标记为“性能”,因此您应该记住某种数字。 IE。如果“保持较小的内存负载”是唯一的目标——一次只读取一条记录,甚至按顺序搜索整个文件是完全可以的......在你得到合理的要求之前,你将无法优化任何东西——“需要。 ..data..很多可能是几次”需要几乎相反的优化。

标签: c# performance memory file-io


【解决方案1】:

您正在谈论一些在实际条目之间具有某些已定义关系的存储数据......也许只有我一个人,但这种情况只需要某种关系数据库。我建议考虑一些便携式数据库,例如 SQL Server CE。它将使您的生活更轻松,并提供您需要的功能。如果你改用 db,你可以准确地查询你需要的数据,而不需要像这样处理大文件。

【讨论】:

  • 我也一直在考虑这个问题,也许这只是更好的选择,但我还不相信。在这种情况下,我需要解析整个文件,这让我开始思考不同的解决方案,但也许我错了。唯一的缺点是初始解析时间会更长并且可能是不必要的(大多数时候用户只是在寻找一些特定的条目)。我的一部分问题仍然与如何阅读文本文件有关。我将暂时保留我的问题,也许稍后将其标记为答案。暂时 +1。
  • 我决定选择 db 选项,因为索引请求/响应行的字节偏移量需要我阅读整行。这是因为它们具有可变长度。为了做到这一点,我将不得不创建我自己的流式阅读器,它不会带来足够的好处来证明它的合理性。如果我选择 db 选项,我可以简单地使用 StreamReader。顺便说一句,我必须检查 SQL Server compact 如何处理它的内存。
【解决方案2】:

如果您通过网络发送请求/响应块,则网络 send() 时间可能比 seek()/read() 和使用 memmap 之间的差异大得多,这无关紧要.要真正实现这种规模,一个简单的解决方案是将文件分解为许多文件,每个文件用于您要服务的每个块(因为“请求”可以达到 25 MB)。然后,您的 HTTP 服务器将尽可能高效地发送该块(甚至可能使用 zerocopy,具体取决于您的网络服务器)。如果你有很多小的“请求”块,而只有几个大块,你可以只突破超过某个阈值的那些。

【讨论】:

  • 我不知道为什么我认为你会通过网络发送这个.. 但无论如何我都会留下我的答案。 Blam 有一个很好的观点。除非你已经看到 seek()/read() 实际上是一个性能问题,否则我不会担心。
  • 感谢您的回答。你没有错,如果用户选择这样做,日志文件可以从网络共享加载。也就是说,我无法控制生成日志和提供日志的过程。所以这对我来说不是一个真正的选择。但是我知道当从网络共享加载日志文件时,使用 memmap 文件没有好处?为此 +1。
【解决方案3】:

我不同意沃尔特的回答。我会去 db 或所有内存。

您为什么如此关心节省内存,因为 600 MB 并不多。您要在内存不足 2 GB 的机器上运行吗?

将统计信息作为键加载到字典中,将值作为具有两个属性的类 - 请求和响应。字典很快。 LINQ 功能强大且速度快。

【讨论】:

  • 是的,运行它的机器有 2GB-3GB 内存。到目前为止,由于机器正在运行所有其他程序,这些机器的内存已经不足。新机器没有预算。根据您的回答,我了解到您不会使用 mepmap 场景而是使用文件流?
  • 当我觉得它是合适的架构时,我只是不会在小于 1 GB 的空间内进行编码。你问是否有人发现你的想法有缺陷。你有它。我认为这是你思维的缺陷。
  • 想要高效并不是我的想法,这是对架构的要求之一。不过还是谢谢你的回答。
  • 酷。高效可以是很多事情。易于编码、内存、cpu、io 和执行时间。如果您的设计参数是最小的内存占用,那我就不清楚了。
猜你喜欢
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
相关资源
最近更新 更多