diff --git a/README.md b/README.md index b19062e..df3afef 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # In-memory Object Graph Stores - + Implementation of an in-memory object graph store, dubbed ϵStore. Our key innovation is a storage model -- epsilon store -- that equates an @@ -23,24 +23,41 @@ programs. Estore db = new Estore("exampleDb", new EstoreOptions().useUnsafe(false)); db.captureAll(alice); + + // MATCH finds Person objects; RETURN puts them in column p Table result = db.query("MATCH (p:`org.estore.example.Person`) RETURN p"); + + result.print(); + Person p = (Person) result.get("p").get(0); + System.out.println(p.name + ", " + p.age); + System.out.println(p.friend.name); ``` `alice` is an ordinary Java `Person` object (name `"Alice"`, age 28). Its `friend` field points to Bob, and Bob's `friend` field points to Charlie, so the in-memory graph is Alice → Bob → Charlie. `captureAll(alice)` walks that - graph from Alice and stores every reachable object; the query then returns - the captured `Person` nodes. + graph from Alice and stores every reachable object. The query finds those + `Person` objects (`MATCH`) and returns them as a table column named `p` + (`RETURN`). Cells in that table are the same heap objects, so they can be + printed, cast to `Person`, and used like any other Java object — including + following `friend` in ordinary Java. 2. Querying object relationships. ```java Table friends = db.query("MATCH (a:`org.estore.example.Person`)-[:friend]->(b:`org.estore.example.Person`) RETURN a, b"); + + for (int i = 0; i < friends.getSize(); i++) { + Person a = (Person) friends.get("a").get(i); + Person b = (Person) friends.get("b").get(i); + System.out.println(a.name + " → " + b.name); + } ``` - This query follows `friend` references between captured `Person` objects and - returns each matched pair. + `-[:friend]->` follows the `friend` field between captured `Person` objects + and returns each matched pair. The loop casts those cells back to `Person` + and prints the names. ## Using ϵStore in a Maven Project diff --git a/estore/src/test/java/org/estore/DbMetadataTest/H2MetadataTest.java b/estore/src/test/java/org/estore/DbMetadataTest/H2MetadataTest.java index 27479cb..5b33b32 100644 --- a/estore/src/test/java/org/estore/DbMetadataTest/H2MetadataTest.java +++ b/estore/src/test/java/org/estore/DbMetadataTest/H2MetadataTest.java @@ -21,13 +21,14 @@ public class H2MetadataTest { private Connection h2Conn1; private Estore estore1; + private boolean profileFlag; @BeforeEach public void setup() throws Exception { String unsafeOpt = System.getProperty("useUnsafe"); Boolean unsafeFlag = (unsafeOpt != null) && (unsafeOpt.equals("true")); String profileOpt = System.getProperty("profile"); - Boolean profileFlag = (profileOpt != null) && (profileOpt.equals("true")); + profileFlag = (profileOpt != null) && (profileOpt.equals("true")); estore1 = new Estore( @@ -111,7 +112,9 @@ public void testCatalogsJDBCRepeat() throws Exception { long t1 = System.nanoTime(); DatabaseMetaData meta1 = h2Conn1.getMetaData(); res1 = meta1.getCatalogs(); - // System.out.println("Total Query Time : " + (System.nanoTime() - t1)); + if (profileFlag) { + System.out.println("Total Query Time : " + (System.nanoTime() - t1)); + } } Set catalogs = new HashSet<>(); @@ -204,7 +207,9 @@ public void testSchemasJDBCRepeat() throws Exception { long t1 = System.nanoTime(); DatabaseMetaData meta1 = h2Conn1.getMetaData(); res1 = meta1.getSchemas(); - // System.out.println("Total Query Time : " + (System.nanoTime() - t1)); + if (profileFlag) { + System.out.println("Total Query Time : " + (System.nanoTime() - t1)); + } } Set schemas = new HashSet<>(); @@ -320,7 +325,9 @@ public void testTablesJDBCRepeat() throws Exception { long t1 = System.nanoTime(); DatabaseMetaData meta1 = h2Conn1.getMetaData(); res1 = meta1.getTables(null, "PUBLIC", "%", new String[] {"TABLE"}); - // System.out.println("Total Query Time : " + (System.nanoTime() - t1)); + if (profileFlag) { + System.out.println("Total Query Time : " + (System.nanoTime() - t1)); + } } Set tables = new HashSet<>(); diff --git a/estore/src/test/java/org/estore/eval/ldbc/finbench/Fin001Test.java b/estore/src/test/java/org/estore/eval/ldbc/finbench/Fin001Test.java index c87861d..3324e3b 100644 --- a/estore/src/test/java/org/estore/eval/ldbc/finbench/Fin001Test.java +++ b/estore/src/test/java/org/estore/eval/ldbc/finbench/Fin001Test.java @@ -33,10 +33,18 @@ public void setupData() throws Exception { readDataSet(); } + private void printQueryTime(String queryName, long startNanos) { + String profileOpt = System.getProperty("profile"); + if (profileOpt != null && profileOpt.equals("true")) { + System.out.println(queryName); + System.out.println( + "Time: " + ((float) (System.nanoTime() - startNanos)) / 1_000_000.0 + "ms"); + } + } + @CompileQuery @Test public void testTw1() { - // System.out.println("Tw1"); long t1 = System.nanoTime(); Table result = estore.query( @@ -44,13 +52,12 @@ public void testTw1() { + " 'George'})-[:Own]->(:`org.estore.eval.ldbc.finbench.util.Account`" + " {accountId: 1020342322, createTime: '26th March', isBlocked: False," + " accountType: 'brokerage account'})"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("Tw1", t1); } @CompileQuery @Test public void testTw2() { - // System.out.println("Tw2"); long t1 = System.nanoTime(); Table result = estore.query( @@ -58,26 +65,24 @@ public void testTw2() { + " companyName: 'Rand'})-[:Own]->(:`org.estore.eval.ldbc.finbench.util.Account`" + " {accountId: 1213243435, createTime: 'February 5th', isBlocked: False," + " accountType: 'brokerage account'})"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("Tw2", t1); } @CompileQuery @Test public void testTw3() { - // System.out.println("Tw3"); long t1 = System.nanoTime(); Table result = estore.query( " MATCH (dst:`org.estore.eval.ldbc.finbench.util.Account` {accountId:" + " 4619004367821865972}), (src:`org.estore.eval.ldbc.finbench.util.Account`" + " {accountId: 99079191802151398}) CREATE (dst)-[:Transfer]->(src)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("Tw3", t1); } @CompileQuery @Test public void testTw4() { - // System.out.println("Tw4"); long t1 = System.nanoTime(); Table result = estore.query( @@ -85,59 +90,55 @@ public void testTw4() { + " 4619004367821865972, accountType:'card'})," + " (src:`org.estore.eval.ldbc.finbench.util.Account` {accountId:" + " 99079191802151398}) CREATE (dst)-[:Withdraw]->(src)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("Tw4", t1); } @CompileQuery @Test public void testTw8() { - // System.out.println("Tw8"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (acc:`org.estore.eval.ldbc.finbench.util.Account` {accountId:" + " 4700350636091245930}), (loan:`org.estore.eval.ldbc.finbench.util.Loan`" + " {loanId: 4684025087442027461}) CREATE (loan)-[:Deposit]->(acc)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("Tw8", t1); } @CompileQuery @Test public void testTw9() { - // System.out.println("Tw9"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (acc:`org.estore.eval.ldbc.finbench.util.Account` {accountId:" + " 4700350636091245930}), (loan:`org.estore.eval.ldbc.finbench.util.Loan`" + " {loanId: 4684025087442027461}) CREATE (acc)-[:Repay]->(loan)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("Tw9", t1); } @CompileQuery @Test public void testTw13() { - // System.out.println("Tw13"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (p1:`org.estore.eval.ldbc.finbench.util.Person` {personId: 2199023255767})," + " (p2:`org.estore.eval.ldbc.finbench.util.Person` {personId: 10995116278183})" + " CREATE (p1)<-[:Guarantee]-(p2)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("Tw13", t1); } @CompileQuery @Test public void testTsr1() { - // System.out.println("Tsr1"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (account:`org.estore.eval.ldbc.finbench.util.Account` {accountId:" + " 4700350636091245930}) RETURN account.createTime, account.isBlocked," + " account.accountType"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("Tsr1", t1); assertEquals(result.get("account.createTime").get(0), "2020-11-11 18:44:24.021"); assertEquals(result.get("account.isBlocked").get(0), false); assertEquals(result.get("account.accountType").get(0), "certificate of deposit"); diff --git a/estore/src/test/java/org/estore/eval/ldbc/snb/Snb01Test.java b/estore/src/test/java/org/estore/eval/ldbc/snb/Snb01Test.java index 5e57bfd..cdf3991 100644 --- a/estore/src/test/java/org/estore/eval/ldbc/snb/Snb01Test.java +++ b/estore/src/test/java/org/estore/eval/ldbc/snb/Snb01Test.java @@ -32,52 +32,57 @@ public void setupData() throws Exception { readDataSet(); } + private void printQueryTime(String queryName, long startNanos) { + String profileOpt = System.getProperty("profile"); + if (profileOpt != null && profileOpt.equals("true")) { + System.out.println(queryName); + System.out.println( + "Time: " + ((float) (System.nanoTime() - startNanos)) / 1_000_000.0 + "ms"); + } + } + @CompileQuery @Test public void testInteractiveDeleteQuery2() { - // System.out.println("InteractiveDeleteQuery2"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (m:`org.estore.eval.ldbc.snb.util.Person`" + "{id:10995116278291})-[likes:LIKES2]->(:`org.estore.eval.ldbc.snb.util.Post`" + "{id:343597383821}) DELETE likes RETURN COUNT(m)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms"); + printQueryTime("InteractiveDeleteQuery2", t1); assertEquals(result.get("COUNT(m)").get(0), 1); } @CompileQuery @Test public void testInteractiveDeleteQuery3() { - // System.out.println("InteractiveDeleteQuery3"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (m:`org.estore.eval.ldbc.snb.util.Person`" + " {id:19791209300608})-[likes:LIKES1]->(:`org.estore.eval.ldbc.snb.util.Comment`" + " {id:549755814421}) DELETE likes RETURN COUNT(m)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms"); + printQueryTime("InteractiveDeleteQuery3", t1); assertEquals(result.get("COUNT(m)").get(0), 1); } @CompileQuery @Test public void testInteractiveDeleteQuery5() { - // System.out.println("InteractiveDeleteQuery5"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (m:`org.estore.eval.ldbc.snb.util.Forum`" + " {id:481036337162})-[hasMember:HAS_MEMBER]->(:`org.estore.eval.ldbc.snb.util.Person`" + " {id:2199023256077}) DELETE hasMember RETURN COUNT(m)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms"); + printQueryTime("InteractiveDeleteQuery5", t1); assertEquals(result.get("COUNT(m)").get(0), 1); } @CompileQuery @Test public void testInteractiveShortQuery1() { - // System.out.println("InteractiveShortQuery1"); long t1 = System.nanoTime(); Table result = estore.query( @@ -86,7 +91,7 @@ public void testInteractiveShortQuery1() { + " RETURN n.firstName AS firstName, n.lastName AS lastName, n.birthday AS" + " birthday, n.locationIP AS locationIP, n.browserUsed AS browserUsed, p.id AS" + " cityId, n.gender AS gender, n.creationDate AS creationDate"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms"); + printQueryTime("InteractiveShortQuery1", t1); assertEquals(result.get("birthday").get(0), 579484800000L); assertEquals(result.get("firstName").get(0), "Min-Jung"); assertEquals(result.get("lastName").get(0), "Park"); @@ -100,14 +105,13 @@ public void testInteractiveShortQuery1() { @CompileQuery @Test public void testInteractiveShortQuery5() { - // System.out.println("InteractiveShortQuery5"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (m:`org.estore.eval.ldbc.snb.util.Comment`" + " {id:206158430603})-[:HAS_CREATOR]->(p:`org.estore.eval.ldbc.snb.util.Person`)" + " RETURN p.id AS personId, p.firstName AS firstName, p.lastName AS lastName"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms"); + printQueryTime("InteractiveShortQuery5", t1); assertEquals(result.get("firstName").get(0), "Rudolf"); assertEquals(result.get("lastName").get(0), "Engel"); assertEquals(result.get("personId").get(0), 2199023256437L); @@ -116,56 +120,52 @@ public void testInteractiveShortQuery5() { @CompileQuery @Test public void testInteractiveUpdateQuery2() { - // System.out.println("InteractiveUpdateQuery2"); long t1 = System.nanoTime(); Table result = estore.query( // error here "MATCH (person:`org.estore.eval.ldbc.snb.util.Person` {id:10995116278291})," + " (post:`org.estore.eval.ldbc.snb.util.Post` {id:481036337280}) CREATE" + " (person)-[r:LIKES2]->(post) RETURN COUNT(r)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms"); + printQueryTime("InteractiveUpdateQuery2", t1); assertEquals(result.get("COUNT(r)").get(0), 1); } @CompileQuery @Test public void testInteractiveUpdateQuery3() { - // System.out.println("InteractiveUpdateQuery3"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (person:`org.estore.eval.ldbc.snb.util.Person` {id:19791209301454})," + " (comment:`org.estore.eval.ldbc.snb.util.Comment` {id:481036337631}) CREATE" + " (person)-[r:LIKES1]->(comment) RETURN COUNT(r)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms"); + printQueryTime("InteractiveUpdateQuery3", t1); assertEquals(result.get("COUNT(r)").get(0), 1); } @CompileQuery @Test public void testInteractiveUpdateQuery5() { - // System.out.println("InteractiveUpdateQuery5"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (f:`org.estore.eval.ldbc.snb.util.Forum` {id:549755813984})," + " (p:`org.estore.eval.ldbc.snb.util.Person` {id:19791209300852}) CREATE" + " (f)-[r:HAS_MEMBER]->(p) RETURN COUNT(r)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms"); + printQueryTime("InteractiveUpdateQuery5", t1); assertEquals(result.get("COUNT(r)").get(0), 1); } @CompileQuery @Test public void testInteractiveUpdateQuery8() { - // System.out.println("InteractiveUpdateQuery8"); long t1 = System.nanoTime(); Table result = estore.query( "MATCH (p1:`org.estore.eval.ldbc.snb.util.Person` {id:4398046512167})," + " (p2:`org.estore.eval.ldbc.snb.util.Person` {id:2199023256816}) CREATE" + " (p1)-[r:KNOWS]->(p2) RETURN COUNT(r)"); - // System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms"); + printQueryTime("InteractiveUpdateQuery8", t1); assertEquals(result.get("COUNT(r)").get(0), 1); } diff --git a/estore/src/test/java/org/estore/example/Person.java b/estore/src/test/java/org/estore/example/Person.java index 2926c49..73e6a3a 100644 --- a/estore/src/test/java/org/estore/example/Person.java +++ b/estore/src/test/java/org/estore/example/Person.java @@ -16,4 +16,9 @@ public Person(String name, int age, Person friend) { this.age = age; this.friend = friend; } + + @Override + public String toString() { + return name + " (" + age + ")"; + } } diff --git a/estore/scripts/gen_codegen_data.py b/scripts/gen_codegen_data.py old mode 100755 new mode 100644 similarity index 81% rename from estore/scripts/gen_codegen_data.py rename to scripts/gen_codegen_data.py index 76397fb..db9f728 --- a/estore/scripts/gen_codegen_data.py +++ b/scripts/gen_codegen_data.py @@ -1,10 +1,16 @@ from collections import defaultdict import json +import os import re import subprocess import sys import statistics +REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +ESTORE_DIR = os.path.join(REPO_ROOT, "estore") +PLUGIN_COORD = "org.estore:estore-maven-plugin:1.0-SNAPSHOT:codegen" +MVN_TEST_FLAGS = "-Dprofile=true -Dsurefire.redirectTestOutputToFile=false" + NUMBER_OF_RUNS = 5 QUERIES = { @@ -51,16 +57,28 @@ def extract_overhead_times(output): results["total"] = total_time return results -def run_command(command): - result = subprocess.run(command, shell=True, capture_output=True, text=True) - output = result.stdout.strip() +def run_command(command, cwd=ESTORE_DIR): + result = subprocess.run(command, shell=True, capture_output=True, text=True, cwd=cwd) + output = (result.stdout + "\n" + result.stderr).strip() + if result.returncode != 0: + print(output) + sys.exit(result.returncode) return output +def install_codegen_plugin(): + run_command("mvn -pl estore-maven-plugin -am install -DskipTests", cwd=REPO_ROOT) + +def run_codegen(): + return run_command("mvn " + PLUGIN_COORD) + def generate_json_sequence(): + install_codegen_plugin() + run_codegen() + def run_test(test_name): times = [] for _ in range(NUMBER_OF_RUNS): - output = run_command(f"mvn test -Dtest={test_name}") + output = run_command(f"mvn test -Dtest={test_name} {MVN_TEST_FLAGS}") _, run_times = extract_times_sorted(output) times.append([float(time) for time in run_times]) return times @@ -81,6 +99,9 @@ def run_test(test_name): json.dump(result, f, indent=2) def generate_json_standalone(): + install_codegen_plugin() + run_codegen() + results = { "original": defaultdict(lambda: defaultdict(lambda: defaultdict(float))), "transformed": defaultdict(lambda: defaultdict(lambda: defaultdict(float))) @@ -91,13 +112,14 @@ def generate_json_standalone(): for bench, queries in QUERIES.items(): for query in queries: test_class = f"{'Transformed' if version == 'transformed' else ''}{bench}Test" - command = f"mvn test -Dtest={test_class}#test{query}" + command = f"mvn test -Dtest={test_class}#test{query} {MVN_TEST_FLAGS}" output = run_command(command) time = extract_time(output) if time is not None: results[version][bench][query][str(run)] = time else: print(f"Error: {version} {bench} {query} failed") + print(output) sys.exit(1) print(f"Run {run + 1}/{NUMBER_OF_RUNS}: {version} {bench} {query} completed") @@ -119,14 +141,18 @@ def generate_json_standalone(): print("Results have been saved to codegen-standalone.json") def generate_json_overhead(): + install_codegen_plugin() results = {} averages = {} for run in range(NUMBER_OF_RUNS): - command = "mvn org.estore:estore-maven-plugin:codegen" - output = run_command(command) + output = run_codegen() data = extract_overhead_times(output) for bench, quries in QUERIES.items(): for query in quries: + if query not in data: + print(f"Error: missing codegen time for {query}") + print(output) + sys.exit(1) if bench not in results: results[bench] = {} averages[bench] = {} @@ -135,6 +161,10 @@ def generate_json_overhead(): averages[bench][query] = [] results[bench][query][str(run)] = data[query] averages[bench][query].append(data[query]) + if data["total"] is None: + print("Error: missing Total Time taken") + print(output) + sys.exit(1) if "total" not in results: results["total"] = {} averages["total"] = [] @@ -157,7 +187,7 @@ def generate_json_overhead(): if __name__ == '__main__': if len(sys.argv) != 2 or sys.argv[1] not in ['standalone', 'sequence', 'overhead']: - print("Usage: python gen_codegen_data.py [standalone|sequence|overhead]") + print("Usage: python scripts/gen_codegen_data.py [standalone|sequence|overhead]") sys.exit(1) if sys.argv[1] == 'sequence': diff --git a/estore/scripts/gen_usecase_data.py b/scripts/gen_usecase_data.py similarity index 79% rename from estore/scripts/gen_usecase_data.py rename to scripts/gen_usecase_data.py index d148744..b3d05b9 100644 --- a/estore/scripts/gen_usecase_data.py +++ b/scripts/gen_usecase_data.py @@ -1,10 +1,18 @@ import json +import os import subprocess import sys +REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +ESTORE_DIR = os.path.join(REPO_ROOT, "estore") +MVN_TEST_FLAGS = "-Dsurefire.redirectTestOutputToFile=false" + def run_command(command): - result = subprocess.run(command, shell=True, capture_output=True, text=True) - output = result.stdout.strip() + result = subprocess.run(command, shell=True, capture_output=True, text=True, cwd=ESTORE_DIR) + output = (result.stdout + "\n" + result.stderr).strip() + if result.returncode != 0: + print(output) + sys.exit(result.returncode) return output def extract_data(output, is_jdbc=False): @@ -46,11 +54,15 @@ def generate_json(data_type): for impl in implementations: impl_data = {} if impl == "jdbc": - command = f"mvn test -Dtest={test_class}#test{query[3:]}JDBCRepeat" + command = f"mvn test -Dtest={test_class}#test{query[3:]}JDBCRepeat -Dprofile=true {MVN_TEST_FLAGS}" total_query_times = [] for _ in range(3): output = run_command(command) total_query_time = extract_data(output, is_jdbc=True)["Total Query Time"] + if total_query_time is None: + print(f"Error: missing Total Query Time for {query} jdbc") + print(output) + sys.exit(1) total_query_times.append(total_query_time) impl_data[impl] = { "Total Query Time": { @@ -64,7 +76,7 @@ def generate_json(data_type): use_unsafe = "true" if impl == "egraph-unsafe" else "false" queryName = query[0].upper() + query[1:] if data_type == 'egraph' else query[3:] suffix = "ESTORE" if data_type == 'h2' else "" - command = f"mvn test -Dtest={test_class}#test{queryName}{suffix}Repeat -DuseUnsafe={use_unsafe} -Dprofile=true" + command = f"mvn test -Dtest={test_class}#test{queryName}{suffix}Repeat -DuseUnsafe={use_unsafe} -Dprofile=true {MVN_TEST_FLAGS}" # print(command) metrics = ["Parse Tree Generation Time", "Query Plan AST Building Time", "Query Execution Time", "Total Query Time"] metric_data = {metric: [] for metric in metrics} @@ -72,6 +84,10 @@ def generate_json(data_type): output = run_command(command) run_data = extract_data(output) for metric in metrics: + if metric not in run_data: + print(f"Error: missing {metric} for {query} {impl}") + print(output) + sys.exit(1) metric_data[metric].append(run_data[metric]) for metric in metrics: values = metric_data[metric] @@ -96,7 +112,7 @@ def generate_json(data_type): if __name__ == '__main__': if len(sys.argv) != 2 or sys.argv[1] not in ['h2', 'egraph']: - print("Usage: python gen_usecase_data.py [h2|egraph]") + print("Usage: python scripts/gen_usecase_data.py [h2|egraph]") sys.exit(1) generate_json(sys.argv[1])