7

所以我有一个“大量”的“非常大”的数字数据 ASCII 文件(总共千兆字节),我的程序需要至少按顺序处理整个文件一次。

关于存储/加载数据的任何建议?我曾考虑将文件转换为二进制文件以使它们更小并加快加载速度。

我应该一次将所有内容都加载到内存中吗?
如果不是,那么打开部分加载数据的好方法是什么?
有哪些与 Java 相关的效率提示?

4

11 回答 11

7

那么,如果处理需要在多个文件和多个缓冲区的数据中跳转怎么办?二进制文件的不断打开和关闭会变得昂贵吗?

我是'memory mapped i/o' 的忠实粉丝,也就是'direct byte buffers'。在 Java 中,它们被称为 映射字节缓冲区,是 java.nio 的一部分。(基本上,这种机制使用操作系统的虚拟内存分页系统来“映射”您的文件并以编程方式将它们呈现为字节缓冲区。操作系统将自动神奇且非常快速地管理将字节移入/移出磁盘和内存。

我推荐这种方法是因为 a) 它对我有用,b) 它可以让你专注于你的算法,让 JVM、操作系统和硬件来处理性能优化。总而言之,他们比我们卑微的程序员更了解什么是最好的。;)

您将如何在您的上下文中使用 MBB?只需为您的每个文件创建一个 MBB 并在您认为合适的时候阅读它们。您只需要存储您的结果。.

顺便说一句:您正在处理多少数据,以 GB 为单位?如果它超过 3-4GB,那么这将不适用于 32 位机器,因为 MBB 实现是平台架构可寻址内存空间的被告。64 位机器和操作系统将带您到 1TB 或 128TB 的可映射数据。

如果您正在考虑性能,那么请了解 Kirk Pepperdine(一位颇有名气的 Java 性能大师)。他参与了一个网站 www.JavaPerformanceTuning.com,其中包含更多 MBB 详细信息:NIO Performance Tips和其他与 Java 性能相关的内容。

于 2008-09-18T13:59:08.973 回答
2

您可能想查看Wide Finder 项目中的条目(在 Google 上搜索“wide finder” java)。

Wide finder 涉及读取日志文件中的大量行,因此请查看 Java 实现,看看哪些在那里有效,哪些无效。

于 2008-09-18T07:00:23.363 回答
1

您可以转换为二进制,但是如果您需要保留原始数据,那么您将拥有 1+ 个数据副本。

在原始 ascii 数据之上构建某种索引可能是切实可行的,这样如果您需要再次浏览数据,您可以在以后更快地完成它。

按顺序回答您的问题:

我应该一次将所有内容都加载到内存中吗?

如果没有,就不会。对于某些文件,您也许可以,但如果您只是按顺序处理,只需对这些内容进行某种缓冲读取,并在此过程中存储您需要的任何内容。

如果不是,那么打开部分加载数据的好方法是什么?

BufferedReaders/etc 是最简单的,尽管您可以深入研究 FileChannel/etc 以使用内存映射 I/O 一次通过数据窗口。

有哪些与 Java 相关的效率提示?

这实际上取决于您对数据本身所做的事情!

于 2008-09-17T21:21:20.027 回答
1

在没有对正在进行的处理类型有任何额外了解的情况下,以下是我完成类似工作时的一些一般想法。

  1. 编写一个应用程序的原型(甚至可能是“扔掉的”),对您的数据集执行一些任意操作。看看它走得有多快。如果你能想到的最简单、最天真的事情是可以接受的快,不用担心!

  2. 如果幼稚的方法不起作用,请考虑对数据进行预处理,以便后续运行将在可接受的时间长度内运行。您提到必须在数据集中“跳来跳去”很多。有什么办法可以预处理出来吗?或者,一个预处理步骤可以是生成更多数据 - 索引数据 - 提供有关数据集关键、必要部分的字节精确位置信息。然后,您的主要处理运行可以利用此信息直接跳转到必要的数据。

因此,总而言之,我的方法是立即尝试一些简单的方法,看看性能如何。也许会好起来的。否则,请考虑分多个步骤处理数据,为不频繁的预处理节省最昂贵的操作。

不要“将所有内容加载到内存中”。只需执行文件访问,让操作系统的磁盘页面缓存来决定您何时可以直接从内存中提取内容。

于 2008-09-17T21:22:21.583 回答
1

这在很大程度上取决于文件中的数据。大型大型机长期以来一直在进行顺序数据处理,但它们通常不会对数据使用随机访问。他们只是一次把它拉成一条线,然后在继续之前处理那么多。

对于随机访问,通常最好使用缓存包装器构建对象,这些缓存包装器知道它们需要构建的数据在文件中的什么位置。在需要时,他们会读取这些数据并自行构建。这样,当内存紧张时,您就可以开始杀掉一些东西,而不必担心以后无法取回它。

于 2008-09-18T14:12:55.353 回答
0

你真的没有给我们足够的信息来帮助你。您是否需要完全加载每个文件才能处理它?或者你可以逐行处理吗?

一次加载整个文件可能会导致性能不佳,即使对于不是非常大的文件也是如此。您最好的选择是定义一个适合您的缓冲区大小,并一次读取/处理缓冲区中的数据。

于 2008-09-17T21:10:55.247 回答
0

我发现 Informatica 是一个非常有用的数据处理工具。好消息是最近的版本甚至允许 Java 转换。如果您正在处理数 TB 的数据,那么可能是时候购买最好的 ETL 工具了。

我假设你想对这里的处理结果做一些事情,比如把它存储在某个地方。

于 2008-09-17T21:11:55.900 回答
0

如果您的数值数据被定期采样并且您需要进行随机访问,请考虑将它们存储在四叉树中。

于 2008-09-17T21:12:06.523 回答
0

我强烈建议使用正则表达式并查看“新”IO nio 包以加快输入速度。然后它应该以您实际期望的千兆字节数据的速度运行。

于 2008-09-17T21:23:41.720 回答
0

如果可能的话,将数据存入数据库。然后,您可以利用所有可用的索引、缓存、内存固定和其他功能。

于 2008-09-18T14:00:46.363 回答
0

如果您需要多次访问数据,请将其加载到数据库中。大多数数据库都有某种批量加载实用程序。如果数据可以全部放入内存,并且您不需要保留它或经常访问它,您可能可以用 Perl 或您最喜欢的脚本语言编写一些简单的东西。

于 2008-09-19T21:05:40.880 回答