gpt4 book ai didi

使用 TDB 的 apache Jena 中的 Java OutOfMemoryError

转载 作者:行者123 更新时间:2023-11-29 08:33:23 25 4
gpt4 key购买 nike

您好,我一直在将 Jena 用于一个项目,现在我正在尝试查询图形以存储在普通文件中,以便使用 Hadoop 进行批处理。

我打开一个 TDB 数据集,然后我使用 LIMIT 和 OFFSET 按页面查询。

我输出每个文件有 100000 个三元组的文件。

然而,在第 10 个文件中,性能下降,在第 15 个文件中,性能下降了 3 倍,在第 22 个文件中,性能下降到 1%。

我的查询是:

SELECT DISTINCT ?S ?P ?O WHERE {?S ?P ?O .} LIMIT 100000 OFFSET X

查询和写入文件的方法在下一个代码块中显示:

public boolean copyGraphPage(int size, int page, String tdbPath, String query, String outputDir, String fileName) throws IllegalArgumentException {
boolean retVal = true;
if (size == 0) {
throw new IllegalArgumentException("The size of the page should be bigger than 0");
}
long offset = ((long) size) * page;
Dataset ds = TDBFactory.createDataset(tdbPath);
ds.begin(ReadWrite.READ);
String queryString = (new StringBuilder()).append(query).append(" LIMIT " + size + " OFFSET " + offset).toString();
QueryExecution qExec = QueryExecutionFactory.create(queryString, ds);
ResultSet resultSet = qExec.execSelect();
List<String> resultVars;
if (resultSet.hasNext()) {
resultVars = resultSet.getResultVars();
String fullyQualifiedPath = joinPath(outputDir, fileName, "txt");
try (BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(
new FileOutputStream(fullyQualifiedPath)), "UTF-8"))) {
while (resultSet.hasNext()) {
QuerySolution next = resultSet.next();
StringBuffer sb = new StringBuffer();
sb.append(next.get(resultVars.get(0)).toString()).append(" ").
append(next.get(resultVars.get(1)).toString()).append(" ").
append(next.get(resultVars.get(2)).toString());
bwr.write(sb.toString());
bwr.newLine();
}
qExec.close();
ds.end();
ds.close();
bwr.flush();
} catch (IOException e) {
e.printStackTrace();
}
resultVars = null;
qExec = null;
resultSet = null;
ds = null;
} else {
retVal = false;
}
return retVal;
}

空变量在那里是因为我不知道那里是否可能存在泄漏。

但是在第 22 个文件之后程序失败并显示以下消息:

java.lang.OutOfMemoryError: GC overhead limit exceeded

at org.apache.jena.ext.com.google.common.cache.LocalCache$EntryFactory$2.newEntry(LocalCache.java:455)
at org.apache.jena.ext.com.google.common.cache.LocalCache$Segment.newEntry(LocalCache.java:2144)
at org.apache.jena.ext.com.google.common.cache.LocalCache$Segment.put(LocalCache.java:3010)
at org.apache.jena.ext.com.google.common.cache.LocalCache.put(LocalCache.java:4365)
at org.apache.jena.ext.com.google.common.cache.LocalCache$LocalManualCache.put(LocalCache.java:5077)
at org.apache.jena.atlas.lib.cache.CacheGuava.put(CacheGuava.java:76)
at org.apache.jena.tdb.store.nodetable.NodeTableCache.cacheUpdate(NodeTableCache.java:205)
at org.apache.jena.tdb.store.nodetable.NodeTableCache._retrieveNodeByNodeId(NodeTableCache.java:129)
at org.apache.jena.tdb.store.nodetable.NodeTableCache.getNodeForNodeId(NodeTableCache.java:82)
at org.apache.jena.tdb.store.nodetable.NodeTableWrapper.getNodeForNodeId(NodeTableWrapper.java:50)
at org.apache.jena.tdb.store.nodetable.NodeTableInline.getNodeForNodeId(NodeTableInline.java:67)
at org.apache.jena.tdb.store.nodetable.NodeTableWrapper.getNodeForNodeId(NodeTableWrapper.java:50)
at org.apache.jena.tdb.solver.BindingTDB.get1(BindingTDB.java:122)
at org.apache.jena.sparql.engine.binding.BindingBase.get(BindingBase.java:121)
at org.apache.jena.sparql.engine.binding.BindingProjectBase.get1(BindingProjectBase.java:52)
at org.apache.jena.sparql.engine.binding.BindingBase.get(BindingBase.java:121)
at org.apache.jena.sparql.engine.binding.BindingProjectBase.get1(BindingProjectBase.java:52)
at org.apache.jena.sparql.engine.binding.BindingBase.get(BindingBase.java:121)
at org.apache.jena.sparql.engine.binding.BindingBase.hashCode(BindingBase.java:201)
at org.apache.jena.sparql.engine.binding.BindingBase.hashCode(BindingBase.java:183)
at java.util.HashMap.hash(HashMap.java:338)
at java.util.HashMap.containsKey(HashMap.java:595)
at java.util.HashSet.contains(HashSet.java:203)
at org.apache.jena.sparql.engine.iterator.QueryIterDistinct.getInputNextUnseen(QueryIterDistinct.java:106)
at org.apache.jena.sparql.engine.iterator.QueryIterDistinct.hasNextBinding(QueryIterDistinct.java:70)
at org.apache.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:114)
at org.apache.jena.sparql.engine.iterator.QueryIterSlice.hasNextBinding(QueryIterSlice.java:76)
at org.apache.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:114)
at org.apache.jena.sparql.engine.iterator.QueryIteratorWrapper.hasNextBinding(QueryIteratorWrapper.java:39)
at org.apache.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:114)
at org.apache.jena.sparql.engine.iterator.QueryIteratorWrapper.hasNextBinding(QueryIteratorWrapper.java:39)
at org.apache.jena.sparql.engine.iterator.QueryIteratorBase.hasNext(QueryIteratorBase.java:114)

Disconnected from the target VM, address: '127.0.0.1:57723', transport: 'socket'

Process finished with exit code 255

内存查看器在查询页面后显示内存使用量的增加:

enter image description here

enter image description here

很明显,Jena LocalCache 正在填满,我已将 Xmx 更改为 2048m,将 Xms 更改为 512m,结果相同。什么都没有改变。

我需要更多内存吗?

我需要清除一些东西吗?

我是否需要停止程序并分段执行?

我的查询有误吗?

OFFSET与它有什么关系吗?

我在一些旧的邮件帖子中读到您可以关闭缓存,但我找不到任何方法来做到这一点。有没有办法关闭缓存?

我知道这是一个非常困难的问题,但我感谢您的帮助。

最佳答案

It is clear that Jena LocalCache is filling up

这是 TDB 节点缓存 - 每个数据集本身通常需要 1.5G(2G 更好)。此缓存在 JVM 的生命周期内持续存在。

一个2G的java堆,按照今天的标准,就是一个小的Java堆。如果你必须使用小堆,你可以尝试在 32 位模式下运行(在 TDB 中称为“直接模式”)但是这样性能较低(主要是因为节点缓存较小并且在这个数据集中你确实有足够的节点导致缓存搅动一个小缓存)。

节点缓存是堆耗尽的主要原因,但查询正在其他地方消耗内存,每个查询,在 DISTINCT 中。

DISTINCT 不一定便宜。它需要记住它看到的所有内容,以了解新行是第一次出现还是已经看到。

Apache Jena 确实优化了(TopN 查询)的某些情况,但截断优化默认为 1000。见代码中的OpTopN

否则它将收集到目前为止看到的所有行。您越深入数据集,节点缓存中的内容就越多,也比 DISTINCT 过滤器中的内容越多。

Do I need more memory?

是的,更多堆。合理的最小值是每个 TDB 数据集 2G,然后是 Java 本身需要的任何大小(比如 0.5G),再加上您的程序和查询工作区。

关于使用 TDB 的 apache Jena 中的 Java OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45992176/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com