【问题标题】:Memory problems, while using UIMA Ruta使用 UIMA Ruta 时出现内存问题
【发布时间】:2017-02-08 09:46:45
【问题描述】:

问题:

我在我的一个项目中使用 UIMA Ruta (v2.3.1),但现在我遇到了一个问题: 内存超过了可解释的大小,但无法弄清楚这个问题在哪里,除了类org.apache.uima.ruta.rule.RuleElementMatch,占了50%内存使用量。

我在我的项目中调用 UIMA Ruta 的 JavaAPI 来设置分析引擎。当我向该引擎发送大约 400kbyte 大小的文本进行分析时,该进程阻塞了大约 700MB 内存,但 GC 没有任何机会释放一些空间。

Ruta 项目:

给定的 Ruta 规则是用 REGEXP 结构构建的,但理论上它们应该会减少内存使用量,因为在特定端点有 UNMARKALL 语句。

是否有人面临同样的高内存消耗情况或有任何建议的解决方案?使用低内存配置文件作为 uima 本身的建议是不可能的,因为响应时间已经在 30 秒左右。增加 JVM 的最大内存不是一种选择。

【问题讨论】:

  • 你使用 Java API 的哪一部分?
  • REGEXP 结构是什么意思? REGEXP 条件还是简单的正则表达式规则? UNAMRKALL 行动遵循什么样的规则?端点是什么意思?
  • 我应该如何理解 JavaAPI 的问题?我们正在按照该 API 的文档中的描述构建一个 AnalysisEngine,添加所有需要的类型系统并推送一个文本以使用 process-method 对该引擎进行分析。正则表达式结构位于我们组合规则的条件部分,就像以下示例一样: (ANY{REGEXP("(H|h)ello")} ANY{REGEXP("(Mr.|Mrs.)" )}){ NOT(IS(Greetings)) ->MARK(Greetings)}
  • 我们连续有六个用于我们要检查的不同语言示例,毕竟,我们通常希望在其中减少类似 ->UNMARKALL(Annotation, {Greetings}) 的 UNMARKALL注释的数量仍在内存中,但这并不能解决问题。我们有这个 400Kbyte 的大文本,将使用 700MB 内存的平均负载进行分析,如果我们提取这段文本的一部分,我们希望减少这个负载,我们的 JVM 有点崩溃,因为内存被这个可疑的 RuleElementMatch 填满类。
  • 我们修复了一些错误,发现了一些 ruta 语句,我们是一些记忆嫌疑人。可以看到改进,但内存仍在泄漏。正如我们所知道的,RutaBasic 类存在一个问题,即保留了一些数组,这些数组只填充了一些单个元素。主要部分在运行时仍然是空的。我们在您的 Jira 中创建了一个问题,UIMA-5306 用于此案例

标签: java memory memory-leaks uima ruta


【解决方案1】:

这可能不是答案,但这里有一些可能有帮助的 cmets。

顾名思义,RutaRuleElementMatch 存储规则元素的匹配项,这是一个 RuleMatch 所必需的,以便识别操作的信息。在 RuleMatch 之后可能会忘记此信息,但有时需要存储它。主要存储分析引擎是否配置调试(参数debugdebugWithMacthes)。然后,记住所有规则匹配和规则元素匹配,以便稍后创建调试注释。如果有很多匹配项,这可能会在当前实现中占用大量内存。

调试配置也用于 Java API,例如 Ruta.select() 或 Ruta.matches()。在较小的数量中,匹配也被记住用于块语句的头部规则。

因此,如果调试已激活,则应将其停用以减少内存使用量。

我认为 400KB 的文本相当多。 Ruta 带来了相当多的开销,这是必需的,但也可以改进/减少。目前,在改进实施之前,有一些最佳实践可以在 ruta 中处理大型文档,即减少内存使用。

在您的用例中,我会切换到一个不同的播种机,它只创建您需要的注释,并且只在您需要它们的地方创建,例如,您是否需要 SPACE 和 BREAK?然后,我会重构规则。您在 cmets 中提到的示例规则效率极低,并且会产生许多 RuleElementMatches。我宁愿建议尽可能使用字典查找,例如与TRIE。您还可以通过限制匹配条件来改进此类规则。在您的示例中,这可能是 W 或某些字典查找的输出。

如果分析显示 RutaRuleElementMatch 使用了大量内存,那么这可能是由调试配置或低效规则引起的。

如果分析显示 RutaBasic 使用了大量内存,那么它是由文档的大小引起的,因此是由注释的数量引起的。减少注释的数量会有所帮助,因为需要将更少的覆盖信息存储在内部列表/数组中。 UNMARKUNMARKALL 也有帮助,但不会达到人们期望的范围,至少在我的用例中是这样。还有一个参数lowMemoryProfile,它可以减少 RutaBasic 的内存使用,但也可以减少你提到的运行时性能。但是,我认为您的规则可以进行很多优化,以便该参数再次成为一个选项。

我希望这会有所帮助。

免责声明:我是 UIMA Ruta 的开发人员

【讨论】:

  • 感谢您的回答,我们正在寻找如何将这些提示转换为 out ruta-project 中的更改。实际上,我们在堆转储中面临着大量的arraylist数组,我们转换了一些效率低下的规则,但它仍然有600m左右的内存峰值,所以我们正在寻找另一种解决方案。一个明显的案例是我们创建的票证,但这并不是唯一一个生成大的空数组的案例。 CASImpl 类生成一些大小固定的堆,因此这是提高内存性能的另一点
  • 您当然也可以拆分文档并单独/顺序处理各个部分。但您可能知道这一点,而这通常不是一个选择。
  • 减少 RutaBasic 注释的数量对您来说可能是一个不错的选择。你真的需要 TokenSeed 注释吗?
  • 我们正在寻找解决方案,因为我们已经有自己的 Seeder,如果还有泄漏的话。拆分文档是一个非常替代但不好的主意,因为我们会丢失它们之间的交叉信息,所以不建议这样做。正如我们在邮件列表中看到的,有些候选人的文档大小约为 18Mb 或 9Gb,因此我们希望能够处理这一数量,因此正在寻求改进我们的规则和代码。
  • 需要将配置参数'lowMemoryProfile'设置为true
猜你喜欢
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 2017-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多