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

关于存储/加载数据有什么建议吗?我考虑过将文件转换为二进制文件,以使它们更小并更快地加载。

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

有帮助吗?

解决方案

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

我是以下的忠实粉丝 “内存映射 I/O”, ,又名 “直接字节缓冲区”. 。在Java中它们被称为 映射字节缓冲区 是 java.nio 的一部分。(基本上,这种机制使用操作系统的虚拟内存分页系统来“映射”您的文件并以编程方式将它们呈现为字节缓冲区。操作系统将自动且快速地管理将字节移入磁盘和内存或从磁盘和内存移出。

我建议这种方法,因为 a) 它对我有用,b) 它会让你专注于你的算法,并让 JVM、操作系统和硬件处理性能优化。通常,他们比我们这些底层程序员更知道什么是最好的。;)

您将如何在您的环境中使用 MBB?只需为每个文件创建一个 MBB 并根据需要阅读它们。您只需要存储您的结果。。

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

如果您正在考虑性能,那么请认识 Kirk Pepperdine(一位颇有名气的 Java 性能大师)。他参与了一个网站 www.JavaPerformanceTuning.com,该网站提供了更多 MBB 详细信息: NIO 性能技巧 以及其他与 Java 性能相关的内容。

其他提示

您可能想查看以下条目 广角取景器项目 (谷歌搜索 “宽查找器”java).

Wide finder 需要读取日志文件中的大量行,因此请查看 Java 实现,看看哪些内容有效,哪些内容无效。

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

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

按顺序回答您的问题:

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

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

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

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

有哪些与 Java 相关的效率技巧?

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

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

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

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

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

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

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

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

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

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

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

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

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

我强烈建议利用正则表达式并研究“新”IO nio 包以加快输入速度。然后它的传输速度应该与您实际期望的千兆字节数据传输速度一样快。

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top