Unverified 提交 871d372b authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1132 from katzyn/visitor

Reduce allocation of ExpressionVisitor instances
......@@ -1435,20 +1435,18 @@ public class Select extends Query {
default:
}
ExpressionVisitor v2 = visitor.incrementQueryLevel(1);
boolean result = true;
for (Expression e : expressions) {
if (!e.isEverything(v2)) {
result = false;
break;
return false;
}
}
if (result && condition != null && !condition.isEverything(v2)) {
result = false;
if (condition != null && !condition.isEverything(v2)) {
return false;
}
if (result && having != null && !having.isEverything(v2)) {
result = false;
if (having != null && !having.isEverything(v2)) {
return false;
}
return result;
return true;
}
@Override
......
......@@ -61,6 +61,37 @@ public class ExpressionVisitor {
public static final ExpressionVisitor EVALUATABLE_VISITOR =
new ExpressionVisitor(EVALUATABLE);
/**
* Count of cached INDEPENDENT and EVALUATABLE visitors with different query
* level.
*/
private static final int CACHED = 8;
/**
* INDEPENDENT listeners with query level 0, 1, ...
*/
private static final ExpressionVisitor[] INDEPENDENT_VISITORS;
/**
* EVALUATABLE listeners with query level 0, 1, ...
*/
private static final ExpressionVisitor[] EVALUATABLE_VISITORS;
static {
ExpressionVisitor[] a = new ExpressionVisitor[CACHED];
a[0] = INDEPENDENT_VISITOR;
for (int i = 1; i < CACHED; i++) {
a[i] = new ExpressionVisitor(INDEPENDENT, i);
}
INDEPENDENT_VISITORS = a;
a = new ExpressionVisitor[CACHED];
a[0] = EVALUATABLE_VISITOR;
for (int i = 1; i < CACHED; i++) {
a[i] = new ExpressionVisitor(EVALUATABLE, i);
}
EVALUATABLE_VISITORS = a;
}
/**
* Request to set the latest modification id (addDataModificationId).
*/
......@@ -148,6 +179,17 @@ public class ExpressionVisitor {
this.maxDataModificationId = null;
}
private ExpressionVisitor(int type, int queryLevel) {
this.type = type;
this.queryLevel = queryLevel;
this.dependencies = null;
this.columns1 = null;
this.columns2 = null;
this.table = null;
this.resolver = null;
this.maxDataModificationId = null;
}
/**
* Create a new visitor object to collect dependencies.
*
......@@ -245,11 +287,18 @@ public class ExpressionVisitor {
* Increment or decrement the query level.
*
* @param offset 1 to increment, -1 to decrement
* @return a clone of this expression visitor, with the changed query level
* @return this visitor or its clone with the changed query level
*/
public ExpressionVisitor incrementQueryLevel(int offset) {
return new ExpressionVisitor(type, queryLevel + offset, dependencies,
columns1, table, resolver, maxDataModificationId, columns2);
if (type == INDEPENDENT) {
offset += queryLevel;
return offset < CACHED ? INDEPENDENT_VISITORS[offset] : new ExpressionVisitor(INDEPENDENT, offset);
} else if (type == EVALUATABLE) {
offset += queryLevel;
return offset < CACHED ? EVALUATABLE_VISITORS[offset] : new ExpressionVisitor(EVALUATABLE, offset);
} else {
return this;
}
}
/**
......@@ -287,6 +336,7 @@ public class ExpressionVisitor {
}
int getQueryLevel() {
assert type == INDEPENDENT || type == EVALUATABLE;
return queryLevel;
}
......
......@@ -45,6 +45,7 @@ import org.h2.test.utils.ProxyCodeGenerator;
import org.h2.test.utils.ResultVerifier;
import org.h2.test.utils.SelfDestructor;
import org.h2.tools.DeleteDbFiles;
import org.h2.util.Utils;
/**
* The base class for all tests.
......@@ -140,7 +141,14 @@ public abstract class TestBase {
init(conf);
start = System.nanoTime();
test();
println("");
if (!config.mvStore) {
/*
* This code is here to debug memory issues with PageStore testing on Travis.
*/
println("(" + (Utils.getMemoryUsed() >> 10) + " MiB used after)");
} else {
println("");
}
} catch (Throwable e) {
println("FAIL " + e.toString());
logError("FAIL " + e.toString(), e);
......
......@@ -18,6 +18,7 @@ import java.util.Random;
import org.h2.test.TestBase;
import org.h2.test.db.Db;
import org.h2.test.db.Db.Prepared;
import org.h2.util.Utils;
/**
* This test executes random SQL statements to test if optimizations are working
......@@ -102,12 +103,12 @@ public class TestFuzzOptimizations extends TestBase {
int size = getSize(100, 1000);
for (int i = 0; i < size; i++) {
long seed = seedGenerator.nextLong();
println("seed: " + seed);
println("testIn() seed: " + seed);
Random random = new Random(seed);
ArrayList<String> params = new ArrayList<>();
String condition = getRandomCondition(random, params, columns,
compares, values);
String message = "seed: " + seed + " " + condition;
String message = "testIn() seed: " + seed + " " + condition;
executeAndCompare(condition, params, message);
if (params.size() > 0) {
for (int j = 0; j < params.size(); j++) {
......@@ -116,9 +117,16 @@ public class TestFuzzOptimizations extends TestBase {
}
executeAndCompare(condition, params, message);
}
if (!config.mvStore) {
/*
* Travis tests have problems with automatic garbage collection, so request a GC
* explicitly and print its results.
*/
println((Utils.getMemoryUsed() >> 10) + " MiB used");
}
}
executeAndCompare("a >=0 and b in(?, 2) and a in(1, ?, null)", Arrays.asList("10", "2"),
"seed=-6191135606105920350L");
"testIn() seed=-6191135606105920350L");
db.execute("drop table test0, test1");
}
......@@ -192,7 +200,7 @@ public class TestFuzzOptimizations extends TestBase {
db.execute("UPDATE TEST SET B = NULL WHERE B = 0");
Random random = new Random();
long seed = random.nextLong();
println("seed: " + seed);
println("testInSelect() seed: " + seed);
for (int i = 0; i < 100; i++) {
String column = random.nextBoolean() ? "A" : "B";
String value = new String[] { "NULL", "0", "A", "B" }[random.nextInt(4)];
......@@ -206,7 +214,7 @@ public class TestFuzzOptimizations extends TestBase {
" FROM TEST I WHERE I." + compare + "=?) ORDER BY 1, 2";
List<Map<String, Object>> a = db.prepare(sql1).set(x).query();
List<Map<String, Object>> b = db.prepare(sql2).set(x).query();
assertTrue("seed: " + seed + " sql: " + sql1 +
assertTrue("testInSelect() seed: " + seed + " sql: " + sql1 +
" a: " + a + " b: " + b, a.equals(b));
}
db.execute("DROP TABLE TEST");
......@@ -217,7 +225,7 @@ public class TestFuzzOptimizations extends TestBase {
db.execute("CREATE TABLE TEST(A INT, B INT, C INT)");
Random random = new Random();
long seed = random.nextLong();
println("seed: " + seed);
println("testGroupSorted() seed: " + seed);
for (int i = 0; i < 100; i++) {
Prepared p = db.prepare("INSERT INTO TEST VALUES(?, ?, ?)");
p.set(new String[] { null, "0", "1", "2" }[random.nextInt(4)]);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论