在30GB XML数据集上搜索正则表达式模式。利用16gb的内存

时间:2020-03-06 14:30:56  来源:igfitidea点击:

我目前有一个Java SAX解析器,该解析器从30GB的XML文件中提取一些信息。

目前是:

  • 读取每个XML节点
  • 将其存储到字符串对象中
  • 在字符串上运行一些正则表达式
  • 将结果存储到数据库

对于几百万个元素。我正在具有16GB内存的计算机上运行此程序,但是内存没有得到充分利用。

有没有一种简单的方法可以动态地"缓冲"输入文件中价值约10gb的数据?

我怀疑我可以手动使用它的"生产者","消费者"多线程版本(一方面加载对象,另一方面使用它们并丢弃),但是该死的,XML现在很古老,没有有效的库来处理这些问题。 ?

解决方案

没有Java经验,对不起,但是也许我们应该更改解析器? SAX应该顺序工作,并且不需要缓冲大多数文件...

我真的不明白我们要使用这么大量的XML做什么,但是我得到的印象是

  • 使用XML对于存储的数据是错误的
  • 我们正在以超出我们应做的方式的缓冲方式(这样做是在放弃SAX解析的所有优势)

除此之外:XML不是古老的,而是被大量和积极地使用。我们认为所有这些交互式网站都将其交互式元素用作什么?

我建议先将大量的XML文件导入本机XML数据库(例如eXist,如果我们正在寻找开放源代码的东西,请不要亲自对其进行测试),然后执行迭代分页查询来一次处理小数据块。

SAX本质上是"事件驱动"的,因此从一个元素到另一个元素应保持的唯一状态是与该元素相关的状态,而不是整个文档。我们还维持其他什么状态,为什么?随着每个"完整"节点(或者一组节点)的出现,我们应该丢弃它们。

我们是否因对数据库执行多次小型提交而变慢了速度?听起来我们几乎总是在从程序中向数据库写入数据,并确保我们不经常进行提交可以提高性能。可能还准备报表,其他标准批量处理技巧可能会有所帮助

除了此早期评论之外,我们还需要更多信息,我们是否有一个方便的探查器,可以了解导致运行缓慢的原因

我们可能想尝试使用Stax而不是SAX,我听说这样做对这种事情更好(我自己还没有使用过)。

首先,尝试找出使我们减速的因素。

  • 从内存解析时,解析器的速度有多快?
  • 大型使用BufferedInputStream是否有帮助?

拆分XML文件容易吗?通常,通过30 GiB转换任何类型的数据都需要花费一些时间,因为我们必须首先从硬盘驱动器加载它,因此,总是受到这种速度的限制。我们可以通过使用Hadoop之类的方式将负载分配到多台计算机吗?

我们可以使用Jibx库,并将XML"节点"绑定到表示它们的对象。我们甚至可以重载ArrayList,然后在添加x个对象时,一次执行所有正则表达式(大概使用执行此逻辑的对象上的方法),然后将其保存到数据库,然后再允许" add"方法再次完成。

Jibx托管在SourceForge上:Jibx

详细说明:我们可以将XML绑定为这些专用String持有者的"集合"。因为我们将其定义为集合,所以必须选择要使用的集合类型。然后,我们可以指定自己的ArrayList实现。

重写add方法,如下所示(忘记了返回类型,例如假定为void):

public void add(Object o) {
    super.add(o);
    if(size() > YOUR_DEFINED_THRESHOLD) {
        flushObjects();
    }
}

YOUR_DEFINED_THRESHOLD

是要存储在arraylist中的对象的数量,直到必须将其刷新到数据库中为止。 flushObjects();只是执行此逻辑的方法。该方法将阻止从XML文件添加对象,直到完成此过程。但是,这没关系,无论如何,数据库的开销可能比文件读取和解析要大得多。

  • 只是为了掩盖基础,Java能够使用16GB吗?我们(显然)需要在64位OS上运行,并且需要使用-d64 -XMx10g(或者想要为其分配多少内存)来运行Java。
  • 内存极不可能成为我们所做工作的限制因素,因此我们真的不应该看到内存被充分利用。我们应该是IO或者CPU绑定的。最有可能的是IO。如果是IO,请确保我们正在缓冲流,然后就完成了;我们唯一可以做的就是购买速度更快的硬盘。
  • 如果我们确实受到CPU的限制,则可能是遇到了正则表达式而不是XML解析的瓶颈。看到这个(引用这个)
  • 捷发
  • 使用JFlex自己滚动
  • 临时设置自己的临时位置,例如使用正则表达式

对于后两个,XML子集越受约束,则使它效率越高。

  • 很难说,但是正如其他人提到的那样,XML本地数据库可能是理想选择。我在这些方面的经验有限,但是我知道至少Berkeley DB XML支持基于XPath的索引。

如果XML中的数据是顺序无关的,那么我们是否可以对进程进行多线程处理以拆分文件,或者可以从文件的不同位置运行多个进程?如果我们不受I / O约束,则应有助于加快速度。