我使用的是neo4j-enterprise edition 2.1.2,并且拥有一个包含229626个节点和1667834个关系的图表。图模型描述哪个人知道具有关系的给定时间戳的另一个人(包括每个人的标识符)。
我尝试使用Neo4j Java Core API(嵌入模式)的现有dijkstra实现来定义最广泛路径问题的算法。不幸的是它表现得很慢。但首先让我向您展示我当前实施的一些细节:
使用自定义CostEvaluator和PathExpander
定义算法PathFinder<WeightedPath> finder = GraphAlgoFactory
.dijkstra(new TimestampPathExpander(RelationType.KNOWS,
Direction.BOTH, 1401746400, depth), new RelationshipCostEvaluator());
数字“1401746400”表示时间戳。应检查每个小于或等于它的关系。我还介绍了一个深度,以最小化路径长度和搜索开销。
TimestampPathExpander
@Override public Iterable<Relationship> expand(Path path, BranchState<String> state) {
List<Relationship> results = new ArrayList<Relationship>();
if(path.length() >= depth) {
return results;
}
for (Relationship r : path.endNode().getRelationships(relationshipType,
direction)) {
// Traverse only relations for the given timestamp
long relationTime = (long) r.getProperty("timestamp");
if (relationTime <= timestamp) {
results.add(r);
}
}
return results;
}
扩展器非常简单。只需查看关系时间戳并将节点添加到结果列表即可。如果生成的路径已达到最大深度,则不会向其添加其他节点。
自定义CostEvaluator
@Override
public Double getCost(Relationship relationship, Direction direction) {
double measure = significance.edgeStrength(relationship);
return measure > 0 ? Double.MAX_VALUE - measure : 0;
}
该度量用作容量值,并根据包括开始和结束节点的度量以及两者的关系计算。因为dijkstra无法处理负边缘权重,所以我只是从大量(Double.Max_value)中减去该度量,从而实现大值被解释为“更便宜”。返回零是不应该触及的角落情况。
这就是我如何预热我的缓存:
for ( Node n : GlobalGraphOperations.at(db).getAllNodes() ) {
n.getPropertyKeys();
for ( Relationship relationship : n.getRelationships() ) {
Node start = relationship.getStartNode();
}
}
我也使用软缓存和以下graph.db属性,其中包含节点标识符的索引以及关系的开始和结束:
neostore.nodestore.db.mapped_memory=3G
neostore.relationshipstore.db.mapped_memory=2G
neostore.propertystore.db.mapped_memory=100M
neostore.propertystore.db.strings.mapped_memory=500M
neostore.propertystore.db.arrays.mapped_memory=100M
neostore.propertystore.db.index.keys.mapped_memory=500M
neostore.propertystore.db.index.mapped_memory=500M
use_memory_mapped_buffers=true
以下是一些始终使用预热缓存的性能指标:
Cache warmup... | Cache warmup...
1742 ms | 30056 ms
1106 ms | 22696 ms
970 ms | 24406 ms
849 ms | 22842 ms
Angela Merkel | Angela Merkel
0.3 | 0.3
CDU | Wladimir Putin
大约3秒钟,只需一跳。那几乎就是这样。是否有一些我不知道的技巧可以改善这些结果?也许我做错了什么?希望有人可以提供帮助。
问候。
答案 0 :(得分:0)
您的系统设置是什么?
你的mmio配置看起来太高了,占用了你所有的堆,所以没有为Neo4j的算法留下任何堆?你有很多记忆吗?我认为你的图表10M表示节点,50M表示关系非常好。您的预热还应该访问时间戳/成本属性,以便加载它们。
neostore.nodestore.db.mapped_memory=10M
neostore.relationshipstore.db.mapped_memory=100M
neostore.propertystore.db.mapped_memory=200M
neostore.propertystore.db.strings.mapped_memory=100M
neostore.propertystore.db.arrays.mapped_memory=0M
# remove both
neostore.propertystore.db.index.keys.mapped_memory=500M
neostore.propertystore.db.index.mapped_memory=500M
您还可以分享此方法的代码吗? significance.edgeStrength(relationship);
我想知道你的0成本是否会反过来影响算法,因为较小的成本会导致更多的路径被考虑,如果成本不变(全部+0)那么它们的权重相等......
如果您的长度小于限制,我只会构造一个ArrayList,否则只返回Collections.emptyList();