diff --git a/java/server/pom.xml b/java/server/pom.xml index 99ff2b1..5cd22a0 100644 --- a/java/server/pom.xml +++ b/java/server/pom.xml @@ -1,141 +1,146 @@ 4.0.0 org.softwareheritage.graph swh-graph 1.0 swh-graph https://www.softwareheritage.org/ UTF-8 11 + + ch.qos.logback + logback-classic + 1.2.3 + junit junit 4.11 test org.hamcrest hamcrest 2.1 test io.javalin javalin 3.0.0 org.slf4j slf4j-simple 1.7.26 com.fasterxml.jackson.core jackson-databind 2.9.8 it.unimi.dsi webgraph-big 3.5.1 it.unimi.dsi fastutil 8.2.2 maven-clean-plugin 3.1.0 maven-resources-plugin 3.0.2 maven-compiler-plugin 3.8.0 -verbose -Xlint:all maven-surefire-plugin 2.22.1 maven-jar-plugin 3.0.2 maven-install-plugin 2.5.2 maven-deploy-plugin 2.8.2 maven-site-plugin 3.7.1 maven-project-info-reports-plugin 3.0.0 maven-assembly-plugin org.softwareheritage.graph.App jar-with-dependencies make-assembly package single org.apache.maven.plugins maven-javadoc-plugin 3.1.1 diff --git a/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java b/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java index a851291..17b7541 100644 --- a/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java +++ b/java/server/src/main/java/org/softwareheritage/graph/Endpoint.java @@ -1,166 +1,230 @@ package org.softwareheritage.graph; import java.util.ArrayList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.softwareheritage.graph.Graph; import org.softwareheritage.graph.SwhId; import org.softwareheritage.graph.SwhPath; import org.softwareheritage.graph.algo.Traversal; /** * REST API endpoints wrapper functions. * * @author Thibault Allançon * @version 1.0 * @since 1.0 */ public class Endpoint { /** Graph where traversal endpoint is performed */ Graph graph; /** Internal traversal API */ Traversal traversal; + /** Timings logger */ + private static final Logger logger = LoggerFactory.getLogger(Endpoint.class); + /** * Constructor. * * @param graph the graph used for traversal endpoint * @param direction a string (either "forward" or "backward") specifying edge orientation * @param edgesFmt a formatted string describing allowed edges (TODO: link API doc) */ public Endpoint(Graph graph, String direction, String edgesFmt) { this.graph = graph; this.traversal = new Traversal(graph, direction, edgesFmt); } + /** + * Returns measurement starting timestamp for logging purposes. + * + * @return timestamp used for time measurement + */ + private long startTiming() { + return System.nanoTime(); + } + + /** + * Ends timing measurement and returns total duration in seconds for logging purposes. + * + * @param startTime measurement starting timestamp + * @return time in seconds elapsed since starting point + */ + private float stopTiming(long startTime) { + long endTime = System.nanoTime(); + float duration = (float) (endTime - startTime) / 1_000_000_000; + return duration; + } + /** * Converts a list of (internal) long node ids to a list of corresponding (external) SWH PIDs. * * @param nodeIds the list of long node ids * @return a list of corresponding SWH PIDs */ private ArrayList convertNodesToSwhIds(ArrayList nodeIds) { + long startTime = this.startTiming(); ArrayList swhIds = new ArrayList<>(); for (long nodeId : nodeIds) { swhIds.add(graph.getSwhId(nodeId)); } + float duration = this.stopTiming(startTime); + logger.debug("convertNodesToSwhIds() took {} s.", duration); return swhIds; } /** * Converts a list of (internal) long node ids to the corresponding {@link SwhPath}. * * @param nodeIds the list of long node ids * @return the corresponding {@link SwhPath} * @see org.softwareheritage.graph.SwhPath */ private SwhPath convertNodesToSwhPath(ArrayList nodeIds) { + long startTime = this.startTiming(); SwhPath path = new SwhPath(); for (long nodeId : nodeIds) { path.add(graph.getSwhId(nodeId)); } + float duration = this.stopTiming(startTime); + logger.debug("convertNodesToSwhPath() took {} s.", duration); return path; } /** * Converts a list of paths made of (internal) long node ids to one made of {@link SwhPath}-s. * * @param pathsNodeId the list of paths with long node ids * @return a list of corresponding {@link SwhPath} * @see org.softwareheritage.graph.SwhPath */ private ArrayList convertPathsToSwhIds(ArrayList> pathsNodeId) { + long startTime = this.startTiming(); ArrayList paths = new ArrayList<>(); for (ArrayList path : pathsNodeId) { paths.add(convertNodesToSwhPath(path)); } + float duration = this.stopTiming(startTime); + logger.debug("convertPathsToSwhIds() took {} s.", duration); return paths; } /** * Leaves endpoint wrapper (performs input/output node ids conversions). * * @param src source node of endpoint call specified as a SwhId * @return the resulting list of SwhId from endpoint call * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.algo.Traversal#leaves(long) */ public ArrayList leaves(SwhId src) { long srcNodeId = graph.getNodeId(src); + + long startTime = this.startTiming(); ArrayList nodeIds = traversal.leaves(srcNodeId); + float duration = this.stopTiming(startTime); + logger.debug("leaves({}) took {} s.", src, duration); + return convertNodesToSwhIds(nodeIds); } /** * Neighbors endpoint wrapper (performs input/output node ids conversions). * * @param src source node of endpoint call specified as a SwhId * @return the resulting list of SwhId from endpoint call * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.algo.Traversal#neighbors(long) */ public ArrayList neighbors(SwhId src) { long srcNodeId = graph.getNodeId(src); + + long startTime = this.startTiming(); ArrayList nodeIds = traversal.neighbors(srcNodeId); + float duration = this.stopTiming(startTime); + logger.debug("neighbors({}) took {} s.", src, duration); + return convertNodesToSwhIds(nodeIds); } /** * Walk endpoint wrapper (performs input/output node ids conversions). * * @param src source node of endpoint call specified as a SwhId * @param dstFmt destination used in endpoint call (TODO: link to API doc) * @param algorithm traversal algorithm used in endpoint call (either "dfs" or "bfs") * @return the resulting {@link SwhPath} from endpoint call * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.SwhPath * @see org.softwareheritage.graph.algo.Traversal#walk */ public SwhPath walk(SwhId src, String dstFmt, String algorithm) { long srcNodeId = graph.getNodeId(src); ArrayList nodeIds = null; // Destination is either a SWH ID or a node type try { SwhId dstSwhId = new SwhId(dstFmt); long dstNodeId = graph.getNodeId(dstSwhId); + + long startTime = this.startTiming(); nodeIds = traversal.walk(srcNodeId, dstNodeId, algorithm); + float duration = this.stopTiming(startTime); + logger.debug("walk({}) took {} s.", src, duration); } catch (IllegalArgumentException ignored1) { try { Node.Type dstType = Node.Type.fromStr(dstFmt); + + long startTime = this.startTiming(); nodeIds = traversal.walk(srcNodeId, dstType, algorithm); + float duration = this.stopTiming(startTime); + logger.debug("walk({}) took {} s.", src, duration); } catch (IllegalArgumentException ignored2) { } } return convertNodesToSwhPath(nodeIds); } /** * VisitNodes endpoint wrapper (performs input/output node ids conversions). * * @param src source node of endpoint call specified as a SwhId * @return the resulting list of SwhId from endpoint call * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.algo.Traversal#visitNodes(long) */ public ArrayList visitNodes(SwhId src) { long srcNodeId = graph.getNodeId(src); + + long startTime = this.startTiming(); ArrayList nodeIds = traversal.visitNodes(srcNodeId); + float duration = this.stopTiming(startTime); + logger.debug("visitNodes({}) took {} s.", src, duration); + return convertNodesToSwhIds(nodeIds); } /** * VisitPaths endpoint wrapper (performs input/output node ids conversions). * * @param src source node of endpoint call specified as a SwhId * @return the resulting list of {@link SwhPath} from endpoint call * @see org.softwareheritage.graph.SwhId * @see org.softwareheritage.graph.SwhPath * @see org.softwareheritage.graph.algo.Traversal#visitPaths(long) */ public ArrayList visitPaths(SwhId src) { long srcNodeId = graph.getNodeId(src); + + long startTime = this.startTiming(); ArrayList> paths = traversal.visitPaths(srcNodeId); + float duration = this.stopTiming(startTime); + logger.debug("visitPaths({}) took {} s.", src, duration); + return convertPathsToSwhIds(paths); } }