Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
import org.apache.hugegraph.HugeFactory;
import org.apache.hugegraph.backend.BackendException;
import org.apache.hugegraph.schema.SchemaManager;
import org.apache.hugegraph.util.Log;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;

import com.datastax.driver.core.exceptions.NoHostAvailableException;

Expand All @@ -34,6 +36,8 @@
*/
public class PerfExample1 extends PerfExampleBase {

private static final Logger LOG = Log.logger(PerfExample1.class);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logger declaration in PerfExample1 and PerfExample2 is added but never used. Consider removing these unused imports and logger declarations to avoid dead code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this time we marked the PerfExampleBase.LOG as private.


public static void main(String[] args) throws Exception {
PerfExample1 tester = new PerfExample1();
tester.test(args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
import org.apache.hugegraph.HugeFactory;
import org.apache.hugegraph.backend.BackendException;
import org.apache.hugegraph.schema.SchemaManager;
import org.apache.hugegraph.util.Log;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;

import com.datastax.driver.core.exceptions.NoHostAvailableException;

Expand All @@ -34,6 +36,8 @@
*/
public class PerfExample2 extends PerfExampleBase {

private static final Logger LOG = Log.logger(PerfExample2.class);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as PerfExample1 - logger is declared but never used. Remove the unused import and logger declaration.


public static void main(String[] args) throws Exception {
PerfExample2 tester = new PerfExample2();
tester.test(args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*/
public class PerfExample4 extends PerfExample3 {

private static final Logger LOG = Log.logger(PerfExample3.class);
private static final Logger LOG = Log.logger(PerfExample4.class);

/**
* Main method
Expand Down Expand Up @@ -79,9 +79,4 @@ protected void testQueryVertex(GraphManager graph,
LOG.info(">>>> query by range index, cost: {}ms", elapsed(current));
}
}

protected static long elapsed(long start) {
long current = System.currentTimeMillis();
return current - start;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package org.apache.hugegraph.example;

import java.util.Iterator;

import org.apache.hugegraph.HugeFactory;
import org.apache.hugegraph.type.define.Directions;
import org.apache.hugegraph.util.Log;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.slf4j.Logger;

/**
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says 'query vertices/adj-edges by ids' but this class only provides vertex and edge querying functionality. The comment should be more specific about what this example demonstrates compared to PerfExample3.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PerfExample3 is a test for: insert vertices with indexes in order

* Perf test for: query vertices/adj-edges by ids
*/
public class PerfExample5 extends PerfExample3 {

private static final Logger LOG = Log.logger(PerfExample5.class);

/**
* Main method
* @param args 3 arguments, 1st should be 1, meaning single thread,
* product of 2nd and 3rd is total number of "person" vertices
* @throws InterruptedException
*/
public static void main(String[] args) throws Exception {
PerfExample5 tester = new PerfExample5();
tester.test(args);

// Stop daemon thread
HugeFactory.shutdown(30L);
}

@Override
protected void testQueryVertex(GraphManager graph,
int threads,
int thread,
int multiple) {
int totalV = 0;
long start = System.currentTimeMillis();
for (int i = 0; i < multiple; i++) {
int j = 0;
for (Object id : this.vertices) {
if (j++ % threads != thread) {
continue;
}
graph.queryVertex(id);
totalV++;
}
}
long cost = elapsed(start);
LOG.info("Query {} vertices with thread({}): {} vertices/s",
totalV, thread, totalV * 1000 / cost);
Comment on lines +67 to +68
Copy link

Copilot AI Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Division by zero error will occur if 'cost' is 0. Add a check to prevent division by zero before calculating vertices/s.

Suggested change
LOG.info("Query {} vertices with thread({}): {} vertices/s",
totalV, thread, totalV * 1000 / cost);
if (cost == 0) {
LOG.info("Query {} vertices with thread({}): N/A vertices/s (cost=0)", totalV, thread);
} else {
LOG.info("Query {} vertices with thread({}): {} vertices/s",
totalV, thread, totalV * 1000 / cost);
}

Copilot uses AI. Check for mistakes.
}

@Override
protected void testQueryEdge(GraphManager graph,
int threads,
int thread,
int multiple) {
int totalV = 0;
int totalE = 0;
long start = System.currentTimeMillis();

for (int i = 0; i < multiple; i++) {
int j = 0;
for (Object id : this.vertices) {
if (j++ % threads != thread) {
continue;
}

Iterator<Edge> edges = graph.queryVertexEdge(id, Directions.OUT);
while (edges.hasNext()) {
edges.next();
totalE++;
}
totalV++;
}
}
long cost = elapsed(start);
LOG.info("Query {} edges of vertices({}) with thread({}): " +
"{} vertices/s, {} edges/s",
totalE, totalV, thread,
totalV * 1000 / cost, totalE * 1000 / cost);
Comment on lines +96 to +99
Copy link

Copilot AI Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Division by zero error will occur if 'cost' is 0. Add a check to prevent division by zero before calculating vertices/s and edges/s.

Copilot uses AI. Check for mistakes.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

package org.apache.hugegraph.example;

import org.apache.hugegraph.HugeFactory;
import org.apache.hugegraph.util.Log;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;

/**
* Perf test for: query vertices/adj-edges by ids with edges insert
*/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is identical to PerfExample5 but this class has different functionality (batch insertion with edges). Update the comment to accurately describe what PerfExample6 demonstrates.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this PerfExample6 test, we insert some edges (one edge per vertex) for adj-edges test.

public class PerfExample6 extends PerfExample5 {

private static final Logger LOG = Log.logger(PerfExample6.class);

/**
* Main method
* @param args 3 arguments, 1st should be 1, meaning single thread,
* product of 2nd and 3rd is total number of "person" vertices
* @throws InterruptedException
*/
public static void main(String[] args) throws Exception {
PerfExample6 tester = new PerfExample6();
tester.test(args);

// Stop daemon thread
HugeFactory.shutdown(30L);
}

@Override
protected void testInsert(GraphManager graph, int times, int multiple) {
final int TIMES = times * multiple;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider extracting the BATCH constant to a class-level constant or making it configurable, as hardcoded values like 100 reduce flexibility for performance testing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the insertion test involves batch, and batch is not a dimension we test, so keep it for now.

final int BATCH = 100;
long total = 0;
Vertex lastV = null;
// Insert in order
for (int i = 0; i < TIMES; i++) {
for (int j = 0; j < BATCH; j++) {
String name = String.format("p-%08d", total++);
Vertex v = graph.addVertex(T.label, "person", "name", name,
"city", "Hongkong", "age", 3);
this.vertices.add(v.id());

if (lastV != null) {
v.addEdge("knows", lastV);
}
lastV = v;
}
graph.tx().commit();
}
LOG.info("Insert {} vertices and {} edges", total, total - 1L);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public abstract class PerfExampleBase {
public static final int SOFTWARE_NUM = 30;
public static final int EDGE_NUM = 100;

protected static final Logger LOG = Log.logger(PerfExampleBase.class);
private static final Logger LOG = Log.logger(PerfExampleBase.class);
Copy link

Copilot AI Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the Logger from 'protected' to 'private' breaks inheritance for subclasses that may need to access the logger. Consider keeping it protected or having subclasses define their own loggers.

Suggested change
private static final Logger LOG = Log.logger(PerfExampleBase.class);
protected static final Logger LOG = Log.logger(PerfExampleBase.class);

Copilot uses AI. Check for mistakes.

protected Set<Object> vertices = Collections.newSetFromMap(new ConcurrentHashMap<>());
protected boolean profile = false;
Expand All @@ -66,6 +66,8 @@ public int test(String[] args) throws Exception {
int times = Integer.parseInt(args[1]);
int multiple = Integer.parseInt(args[2]);
this.profile = Boolean.parseBoolean(args[3]);
System.out.printf("Run: threads=%s times=%s multiple=%s profile=%s\n",
threadCount, times, multiple, this.profile);

// NOTE: this test with HugeGraph is for local,
// change it into a client if test with restful server from remote
Expand Down Expand Up @@ -118,7 +120,7 @@ public void testQueryVertexPerf(GraphManager graph, int threadCount, int times,
this.testQueryVertex(graph, threadCount, i, multiple);
}, threadCount);

final long size = (long) (PERSON_NUM + SOFTWARE_NUM) * threadCount * times;
final long size = this.vertices.size();
LOG.info("Query rate with threads: {} vertices/s, " +
"query total vertices {}, cost time: {}ms",
size * 1000 / cost, size, cost);
Expand All @@ -130,7 +132,7 @@ public void testQueryEdgePerf(GraphManager graph, int threadCount, int times, in
this.testQueryEdge(graph, threadCount, i, multiple);
}, threadCount);

final long size = (long) (PERSON_NUM + SOFTWARE_NUM) * threadCount * times;
final long size = this.vertices.size();
LOG.info("Query rate with threads: {} vedges/s, " +
"query total vedges {}, cost time: {}ms",
size * 1000 / cost, size, cost);
Expand Down Expand Up @@ -188,26 +190,29 @@ protected long execute(GraphManager graph, Consumer<Integer> task,

protected abstract void testInsert(GraphManager graph, int times, int multiple);

protected void testQueryVertex(GraphManager graph, int threads, int thread, int multiple) {
int i = 0;
int j = 0;
int total = 0;
for (Object id : this.vertices) {
if (i++ % multiple != 0) {
continue;
}
if (j++ % threads != thread) {
continue;
}

LOG.debug("Query vertex {}: {}", i, id);
Vertex vertex = graph.queryVertex(id);
if (!vertex.id().equals(id)) {
LOG.warn("Query vertex by id {} returned {}", id, vertex);
protected void testQueryVertex(GraphManager graph,
int threads,
int thread,
int multiple) {
int totalV = 0;
long start = System.currentTimeMillis();
for (int i = 0; i < multiple; i++) {
int j = 0;
for (Object id : this.vertices) {
if (j++ % threads != thread) {
continue;
}
LOG.debug("Query vertex {}: {}", i, id);
Vertex vertex = graph.queryVertex(id);
if (!vertex.id().equals(id)) {
LOG.warn("Query vertex by id {} returned {}", id, vertex);
}
totalV++;
}
total++;
}
LOG.debug("Query vertices with thread({}): {}", thread, total);
long cost = elapsed(start);
LOG.info("Query {} vertices with thread({}): {} vertices/s",
totalV, thread, totalV * 1000 / cost);
Comment on lines +214 to +215
Copy link

Copilot AI Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Division by zero error will occur if 'cost' is 0. Add a check to prevent division by zero before calculating vertices/s.

Suggested change
LOG.info("Query {} vertices with thread({}): {} vertices/s",
totalV, thread, totalV * 1000 / cost);
if (cost == 0) {
LOG.info("Query {} vertices with thread({}): N/A vertices/s (cost=0ms)", totalV, thread);
} else {
LOG.info("Query {} vertices with thread({}): {} vertices/s",
totalV, thread, totalV * 1000 / cost);
}

Copilot uses AI. Check for mistakes.
}

protected void testQueryEdge(GraphManager graph, int threads, int thread, int multiple) {
Expand Down Expand Up @@ -235,6 +240,11 @@ protected void testQueryEdge(GraphManager graph, int threads, int thread, int mu
totalV, thread, totalE);
}

protected static long elapsed(long start) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good refactoring to move the elapsed() method to the base class where it can be reused by all performance examples.

long current = System.currentTimeMillis();
return current - start;
}

protected static class GraphManager {

private final HugeGraph hugegraph;
Expand Down
Loading