Skip to content

Commit

Permalink
use IntObjectMap and IntIntMap to improve shortest path
Browse files Browse the repository at this point in the history
Change-Id: I960167c1c87d1ebcebe29a5a7073d6251239d29d
  • Loading branch information
zhoney committed Mar 30, 2021
1 parent 3cf3fbf commit 97d3f65
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,39 @@

package com.baidu.hugegraph.traversal.algorithm;

import org.eclipse.collections.impl.map.mutable.primitive.LongObjectHashMap;
import org.eclipse.collections.impl.map.mutable.primitive.ObjectLongHashMap;
import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap;

import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.backend.id.Id;

public class IdMapping {

private LongObjectHashMap long2IdMap;
private ObjectLongHashMap id2LongMap;
private long nextLong;
private static final int MAGIC = 1 << 16;
private IntObjectHashMap int2IdMap;

public IdMapping() {
this.long2IdMap = new LongObjectHashMap();
this.id2LongMap = new ObjectLongHashMap();
this.nextLong = 0L;
this.int2IdMap = new IntObjectHashMap();
}

public long getLong(Id id) {
if (this.id2LongMap.containsKey(id)) {
return this.id2LongMap.get(id);
public int getCode(Id id) {
int key = id.hashCode();
for (int i = 1; i > 0; i <<= 1) {
for (int j = 0; i >= MAGIC && j < 10; j++) {
Id existed = (Id) this.int2IdMap.get(key);
if (existed == null) {
this.int2IdMap.put(key, id);
return key;
}
if (existed.equals(id)) {
return key;
}
key = key + i + j;
}
}
this.nextLong++;
this.id2LongMap.put(id, this.nextLong);
this.long2IdMap.put(this.nextLong, id);
return this.nextLong;
throw new HugeException("Failed to get code for id: %s", id);
}

public Id getId(long code) {
return (Id) this.long2IdMap.get(code);
public Id getId(int code) {
return (Id) this.int2IdMap.get(code);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@

import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.eclipse.collections.api.iterator.LongIterator;
import org.eclipse.collections.impl.map.mutable.primitive.LongLongHashMap;
import org.eclipse.collections.api.iterator.IntIterator;
import org.eclipse.collections.impl.map.mutable.primitive.IntIntHashMap;
import org.eclipse.collections.impl.set.mutable.primitive.LongHashSet;

import com.baidu.hugegraph.HugeGraph;
Expand Down Expand Up @@ -142,8 +142,8 @@ private class Traverser {
// TODO: change Map to Set to reduce memory cost
private IdMapping idMapping;

private Stack<LongLongHashMap> sourceLayers;
private Stack<LongLongHashMap> targetLayers;
private Stack<IntIntHashMap> sourceLayers;
private Stack<IntIntHashMap> targetLayers;


private LongHashSet accessed = new LongHashSet();
Expand All @@ -161,12 +161,12 @@ public Traverser(Id sourceV, Id targetV, Directions dir,
Map<Id, String> labels, long degree,
long skipDegree, long capacity) {
this.idMapping = new IdMapping();
long sourceCode = this.code(sourceV);
long targetCode = this.code(targetV);
LongLongHashMap firstSourceLayer = new LongLongHashMap();
LongLongHashMap firstTargetLayer = new LongLongHashMap();
firstSourceLayer.put(sourceCode, 0L);
firstTargetLayer.put(targetCode, 0L);
int sourceCode = this.code(sourceV);
int targetCode = this.code(targetV);
IntIntHashMap firstSourceLayer = new IntIntHashMap();
IntIntHashMap firstTargetLayer = new IntIntHashMap();
firstSourceLayer.put(sourceCode, 0);
firstTargetLayer.put(targetCode, 0);
this.sourceLayers = new Stack<>();
this.targetLayers = new Stack<>();
this.sourceLayers.push(firstSourceLayer);
Expand All @@ -188,17 +188,17 @@ public Traverser(Id sourceV, Id targetV, Directions dir,
*/
public PathSet forward(boolean all) {
PathSet paths = new PathSet();
LongLongHashMap newLayer = new LongLongHashMap();
IntIntHashMap newLayer = new IntIntHashMap();
long degree = this.skipDegree > 0L ? this.skipDegree : this.degree;

assert !this.sourceLayers.isEmpty();
assert !this.targetLayers.isEmpty();
LongLongHashMap sourceTopLayer = this.sourceLayers.peek();
LongLongHashMap targetTopLayer = this.targetLayers.peek();
IntIntHashMap sourceTopLayer = this.sourceLayers.peek();
IntIntHashMap targetTopLayer = this.targetLayers.peek();

LongIterator iterator = sourceTopLayer.keySet().longIterator();
IntIterator iterator = sourceTopLayer.keySet().intIterator();
while (iterator.hasNext()) {
long sourceCode = iterator.next();
int sourceCode = iterator.next();
Iterator<Edge> edges = edgesOfVertex(this.id(sourceCode),
this.direction,
this.labels, degree);
Expand All @@ -207,7 +207,7 @@ public PathSet forward(boolean all) {
while (edges.hasNext()) {
HugeEdge edge = (HugeEdge) edges.next();
Id target = edge.id().otherVertexId();
long targetCode = this.code(target);
int targetCode = this.code(target);

// If cross point exists, shortest path found, concat them
if (targetTopLayer.containsKey(targetCode)) {
Expand Down Expand Up @@ -247,19 +247,19 @@ public PathSet forward(boolean all) {
*/
public PathSet backward(boolean all) {
PathSet paths = new PathSet();
LongLongHashMap newLayer = new LongLongHashMap();
IntIntHashMap newLayer = new IntIntHashMap();
long degree = this.skipDegree > 0L ? this.skipDegree : this.degree;

assert !this.sourceLayers.isEmpty();
assert !this.targetLayers.isEmpty();
LongLongHashMap sourceTopLayer = this.targetLayers.peek();
LongLongHashMap targetTopLayer = this.sourceLayers.peek();
IntIntHashMap sourceTopLayer = this.targetLayers.peek();
IntIntHashMap targetTopLayer = this.sourceLayers.peek();

Directions opposite = this.direction.opposite();

LongIterator iterator = sourceTopLayer.keySet().longIterator();
IntIterator iterator = sourceTopLayer.keySet().intIterator();
while (iterator.hasNext()) {
long sourceCode = iterator.next();
int sourceCode = iterator.next();
Iterator<Edge> edges = edgesOfVertex(this.id(sourceCode),
opposite, this.labels,
degree);
Expand All @@ -268,7 +268,7 @@ public PathSet backward(boolean all) {
while (edges.hasNext()) {
HugeEdge edge = (HugeEdge) edges.next();
Id target = edge.id().otherVertexId();
long targetCode = this.code(target);
int targetCode = this.code(target);

// If cross point exists, shortest path found, concat them
if (targetTopLayer.containsKey(targetCode)) {
Expand Down Expand Up @@ -311,36 +311,36 @@ private boolean superNode(Id vertex, Directions direction) {
return IteratorUtils.count(edges) >= this.skipDegree;
}

private Path getPath(long source, long target) {
private Path getPath(int source, int target) {
int sourceLayerSize = this.sourceLayers.size();
int targetLayerSize = this.targetLayers.size();

List<Id> ids = new ArrayList<>(sourceLayerSize + targetLayerSize);

ids.add(this.id(source));
long value = source;
int value = source;
for (int i = sourceLayerSize - 1; i > 0 ; i--) {
LongLongHashMap layer = this.sourceLayers.elementAt(i);
IntIntHashMap layer = this.sourceLayers.elementAt(i);
value = layer.get(value);
ids.add(this.id(value));
}
Collections.reverse(ids);
ids.add(this.id(target));
value = target;
for (int i = this.targetLayers.size() - 1; i > 0 ; i--) {
LongLongHashMap layer = this.targetLayers.elementAt(i);
IntIntHashMap layer = this.targetLayers.elementAt(i);
value = layer.get(value);
ids.add(this.id(value));
}
return new Path(ids);
}

private Id id(long code) {
private Id id(int code) {
return this.idMapping.getId(code);
}

private long code(Id id) {
return this.idMapping.getLong(id);
private int code(Id id) {
return this.idMapping.getCode(id);
}
}
}

0 comments on commit 97d3f65

Please sign in to comment.