![](/img/trans.png)
[英]Performance of Java API versus Python with Cypher for Neo4J
[英]Neo4j Java API: widest path algorithm performance issues
我使用的是neo4j-enterprise版本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; }
擴展器確實很簡單。 只需查看關系時間戳並將節點添加到結果列表即可。 如果生成的路徑已達到最大深度,則不會向其添加任何其他節點。
自定義費用評估器
@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秒鍾,僅需跳一跳。 差不多了 有一些我不知道的技巧可以改善這些結果嗎? 也許我做錯了什么? 希望有人可以幫忙。
問候。
您的系統設置是什么?
看來您的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();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.