Skip to content

Commit 891b109

Browse files
[MOD] Filters, comparisons: micro optimizations
1 parent b5814ca commit 891b109

File tree

10 files changed

+51
-81
lines changed

10 files changed

+51
-81
lines changed

basex-core/src/main/java/org/basex/query/expr/CmpG.java

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ static OpG get(final OpV opV) {
152152

153153
/** Operator. */
154154
OpG op;
155-
/** Type check at runtime. */
156-
boolean check = true;
155+
/** Indicates if input is comparable. */
156+
boolean comparable;
157157

158158
/**
159159
* Constructor.
@@ -211,7 +211,7 @@ public final Expr optimize(final CompileContext cc) throws QueryException {
211211
if(expr == this) expr = CmpR.get(cc, this);
212212
if(expr == this) expr = CmpSR.get(cc, this);
213213
if(expr == this) {
214-
// skip runtime type check if items are known to be comparable (covers most common types)
214+
// skip runtime type check if items are known to be comparable
215215
final SeqType st1 = expr1.seqType(), st2 = expr2.seqType();
216216
final Type type1 = st1.type, type2 = st2.type;
217217
if(type1 == type2 && !type1.oneOf(AtomType.ANY_ATOMIC_TYPE, AtomType.ITEM)
@@ -220,23 +220,23 @@ public final Expr optimize(final CompileContext cc) throws QueryException {
220220
|| type1.isStringOrUntyped() && type2.isStringOrUntyped()
221221
|| type1.instanceOf(AtomType.BINARY) && type2.instanceOf(AtomType.BINARY)
222222
|| type1.instanceOf(AtomType.DURATION) && type2.instanceOf(AtomType.DURATION)) {
223-
check = false;
223+
comparable = true;
224224
}
225225

226226
// choose best implementation
227227
if(st1.zeroOrOne() && !st1.mayBeArray() && st2.zeroOrOne() && !st2.mayBeArray()) {
228228
// simple comparisons
229-
if(!(this instanceof CmpSimpleG)) expr = new CmpSimpleG(expr1, expr2, op, info, check);
229+
if(!(this instanceof CmpSimpleG)) expr = copyType(new CmpSimpleG(expr1, expr2, op, info));
230230
} else if(op == OpG.EQ && sc().collation == null && !st2.zeroOrOne() && (
231231
type1.isNumber() && type2.isNumber() ||
232232
type1.isStringOrUntyped() && type2.isStringOrUntyped() ||
233233
type1 == AtomType.BOOLEAN && type2 == AtomType.BOOLEAN
234234
)) {
235235
// hash-based comparisons
236-
if(!(this instanceof CmpHashG)) expr = new CmpHashG(expr1, expr2, op, info);
236+
if(!(this instanceof CmpHashG)) expr = copyType(new CmpHashG(expr1, expr2, op, info));
237237
} else if(op == OpG.EQ && expr2 instanceof Range && type1.isNumberOrUntyped()) {
238238
// range comparisons
239-
if(!(this instanceof CmpRangeG)) expr = new CmpRangeG(expr1, expr2, op, info);
239+
if(!(this instanceof CmpRangeG)) expr = copyType(new CmpRangeG(expr1, expr2, op, info));
240240
}
241241

242242
// pre-evaluate expression; discard hashed results
@@ -351,9 +351,10 @@ boolean compare(final Iter iter1, final Iter iter2, final long size1, final long
351351
* @throws QueryException query exception
352352
*/
353353
final boolean eval(final Item item1, final Item item2) throws QueryException {
354-
if(check && !(item1.comparable(item2) || item1.type.isUntyped() || item2.type.isUntyped()))
355-
throw compareError(item1, item2, info);
356-
return op.value().eval(item1, item2, info);
354+
if(comparable || item1.comparable(item2) || item1.type.isUntyped() || item2.type.isUntyped()) {
355+
return op.value().eval(item1.compare(item2, null, false, info));
356+
}
357+
throw compareError(item1, item2, info);
357358
}
358359

359360
/**
@@ -546,11 +547,20 @@ public final boolean indexAccessible(final IndexInfo ii) throws QueryException {
546547

547548
@Override
548549
public CmpG copy(final CompileContext cc, final IntObjectMap<Var> vm) {
549-
final CmpG cmp = new CmpG(info, exprs[0].copy(cc, vm), exprs[1].copy(cc, vm), op);
550-
cmp.check = check;
551-
return copyType(cmp);
550+
return copyType(new CmpG(info, exprs[0].copy(cc, vm), exprs[1].copy(cc, vm), op));
551+
}
552+
553+
/**
554+
* Finalizes the copy of a general comparison.
555+
* @param cmp comparison
556+
* @return enriched expression
557+
*/
558+
final CmpG copyType(final CmpG cmp) {
559+
cmp.comparable = comparable;
560+
return super.copyType(cmp);
552561
}
553562

563+
554564
@Override
555565
public final boolean equals(final Object obj) {
556566
return this == obj || obj instanceof final CmpG cmp && op == cmp.op && super.equals(obj);

basex-core/src/main/java/org/basex/query/expr/CmpSimpleG.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,9 @@ public final class CmpSimpleG extends CmpG {
1919
* @param expr2 second expression
2020
* @param op operator
2121
* @param info input info (can be {@code null})
22-
* @param check check flag
2322
*/
24-
CmpSimpleG(final Expr expr1, final Expr expr2, final OpG op, final InputInfo info,
25-
final boolean check) {
23+
CmpSimpleG(final Expr expr1, final Expr expr2, final OpG op, final InputInfo info) {
2624
super(info, expr1, expr2, op);
27-
this.check = check;
2825
}
2926

3027
@Override
@@ -33,12 +30,13 @@ public boolean test(final QueryContext qc, final InputInfo ii, final long pos)
3330
final Item item1 = exprs[0].item(qc, info);
3431
if(item1.isEmpty()) return false;
3532
final Item item2 = exprs[1].item(qc, info);
36-
return !item2.isEmpty() && eval(item1, item2);
33+
if(item2.isEmpty()) return false;
34+
return eval(item1, item2);
3735
}
3836

3937
@Override
4038
public CmpG copy(final CompileContext cc, final IntObjectMap<Var> vm) {
41-
return copyType(new CmpSimpleG(exprs[0].copy(cc, vm), exprs[1].copy(cc, vm), op, info, check));
39+
return copyType(new CmpSimpleG(exprs[0].copy(cc, vm), exprs[1].copy(cc, vm), op, info));
4240
}
4341

4442
@Override

basex-core/src/main/java/org/basex/query/expr/CmpV.java

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,7 @@ public enum OpV {
2828
/** Item comparison: less or equal. */
2929
LE("le") {
3030
@Override
31-
public boolean eval(final Item item1, final Item item2, final InputInfo info)
32-
throws QueryException {
33-
final int v = item1.compare(item2, null, false, info);
34-
return v != Item.NAN_DUMMY && v <= 0;
35-
}
31+
public boolean eval(final int v) { return v != Item.NAN_DUMMY && v <= 0; }
3632
@Override
3733
public OpV swap() { return GE; }
3834
@Override
@@ -44,11 +40,7 @@ public boolean eval(final Item item1, final Item item2, final InputInfo info)
4440
/** Item comparison: less. */
4541
LT("lt") {
4642
@Override
47-
public boolean eval(final Item item1, final Item item2, final InputInfo info)
48-
throws QueryException {
49-
final int v = item1.compare(item2, null, false, info);
50-
return v != Item.NAN_DUMMY && v < 0;
51-
}
43+
public boolean eval(final int v) { return v != Item.NAN_DUMMY && v < 0; }
5244
@Override
5345
public OpV swap() { return GT; }
5446
@Override
@@ -60,10 +52,7 @@ public boolean eval(final Item item1, final Item item2, final InputInfo info)
6052
/** Item comparison: greater of equal. */
6153
GE("ge") {
6254
@Override
63-
public boolean eval(final Item item1, final Item item2, final InputInfo info)
64-
throws QueryException {
65-
return item1.compare(item2, null, false, info) >= 0;
66-
}
55+
public boolean eval(final int v) { return v >= 0; }
6756
@Override
6857
public OpV swap() { return LE; }
6958
@Override
@@ -75,10 +64,7 @@ public boolean eval(final Item item1, final Item item2, final InputInfo info)
7564
/** Item comparison: greater. */
7665
GT("gt") {
7766
@Override
78-
public boolean eval(final Item item1, final Item item2, final InputInfo info)
79-
throws QueryException {
80-
return item1.compare(item2, null, false, info) > 0;
81-
}
67+
public boolean eval(final int v) { return v > 0; }
8268
@Override
8369
public OpV swap() { return LT; }
8470
@Override
@@ -90,10 +76,7 @@ public boolean eval(final Item item1, final Item item2, final InputInfo info)
9076
/** Item comparison: equal. */
9177
EQ("eq") {
9278
@Override
93-
public boolean eval(final Item item1, final Item item2, final InputInfo info)
94-
throws QueryException {
95-
return item1.equal(item2, null, info);
96-
}
79+
public boolean eval(final int v) { return v == 0; }
9780
@Override
9881
public OpV swap() { return EQ; }
9982
@Override
@@ -105,10 +88,7 @@ public boolean eval(final Item item1, final Item item2, final InputInfo info)
10588
/** Item comparison: not equal. */
10689
NE("ne") {
10790
@Override
108-
public boolean eval(final Item item1, final Item item2, final InputInfo info)
109-
throws QueryException {
110-
return !item1.equal(item2, null, info);
111-
}
91+
public boolean eval(final int v) { return v != 0; }
11292
@Override
11393
public OpV swap() { return NE; }
11494
@Override
@@ -130,14 +110,10 @@ public boolean eval(final Item item1, final Item item2, final InputInfo info)
130110

131111
/**
132112
* Evaluates the expression.
133-
* @param item1 first item
134-
* @param item2 second item
135-
* @param info input info (can be {@code null})
113+
* @param diff difference
136114
* @return result
137-
* @throws QueryException query exception
138115
*/
139-
public abstract boolean eval(Item item1, Item item2, InputInfo info)
140-
throws QueryException;
116+
public abstract boolean eval(int diff);
141117

142118
/**
143119
* Swaps the comparator.
@@ -257,7 +233,7 @@ public boolean test(final QueryContext qc, final InputInfo ii, final long pos)
257233
* @throws QueryException query exception
258234
*/
259235
private boolean test(final Item item1, final Item item2) throws QueryException {
260-
if(item1.comparable(item2)) return opV.eval(item1, item2, info);
236+
if(item1.comparable(item2)) return opV.eval(item1.compare(item2, null, false, info));
261237
throw compareError(item1, item2, info);
262238
}
263239

basex-core/src/main/java/org/basex/query/expr/IterFilter.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,16 @@ public final class IterFilter extends Filter {
2626
}
2727

2828
@Override
29-
public Iter iter(final QueryContext qc) {
29+
public Iter iter(final QueryContext qc) throws QueryException {
3030
return new Iter() {
31-
Iter iter;
31+
final Iter iter = root.iter(qc);
3232

3333
@Override
3434
public Item next() throws QueryException {
35-
// first call - initialize iterator
36-
if(iter == null) iter = root.iter(qc);
37-
// filter sequence
38-
for(Item item; (item = qc.next(iter)) != null;) {
39-
if(test(item, qc)) return item;
35+
final QueryContext q = qc;
36+
final Iter ir = iter;
37+
for(Item item; (item = q.next(ir)) != null;) {
38+
if(test(item, q)) return item;
4039
}
4140
return null;
4241
}

basex-core/src/main/java/org/basex/query/expr/Preds.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ public final Expr flattenEbv(final Expr root, final boolean ebv, final CompileCo
305305
* Checks if at least one of the predicates may be positional.
306306
* @return result of check
307307
*/
308-
public boolean mayBePositional() {
308+
public final boolean mayBePositional() {
309309
for(final Expr expr : exprs) {
310310
if(mayBePositional(expr)) return true;
311311
}

basex-core/src/main/java/org/basex/query/func/fn/FnIndexOf.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public Iter iter(final QueryContext qc) throws QueryException {
3131
public Itr next() throws QueryException {
3232
for(Item item; (item = qc.next(input)) != null;) {
3333
++c;
34-
if(item.comparable(search) && item.equal(search, collation, info)) {
34+
if(item.comparable(search) && item.compare(search, collation, false, info) == 0) {
3535
return Itr.get(c);
3636
}
3737
}
@@ -50,7 +50,9 @@ public Value value(final QueryContext qc) throws QueryException {
5050
int c = 0;
5151
for(Item item; (item = qc.next(input)) != null;) {
5252
++c;
53-
if(item.comparable(search) && item.equal(search, collation, info)) list.add(c);
53+
if(item.comparable(search) && item.compare(search, collation, false, info) == 0) {
54+
list.add(c);
55+
}
5456
}
5557
return IntSeq.get(list.finish());
5658
}

basex-core/src/main/java/org/basex/query/util/hash/HashItemSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public HashItemSet(final Mode mode, final InputInfo info, final long capacity) {
3939
super(capacity);
4040
equal = switch(mode) {
4141
case ATOMIC -> Item::atomicEqual;
42-
case EQUAL -> (k1, k2) -> k1.equal(k2, null, info);
42+
case EQUAL -> (k1, k2) -> k1.compare(k2, null, false, info) == 0;
4343
default -> new DeepEqual(info)::equal;
4444
};
4545
keys = new Item[capacity()];

basex-core/src/main/java/org/basex/query/value/item/Item.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.basex.io.out.DataOutput;
1515
import org.basex.query.*;
1616
import org.basex.query.expr.*;
17-
import org.basex.query.expr.CmpV.*;
1817
import org.basex.query.func.fn.*;
1918
import org.basex.query.iter.*;
2019
import org.basex.query.util.*;
@@ -168,19 +167,6 @@ public boolean comparable(final Item item) {
168167
return type == item.type;
169168
}
170169

171-
/**
172-
* Compares items for equality. Called by {@link OpV}.
173-
* @param item item to be compared
174-
* @param coll collation (can be {@code null})
175-
* @param ii input info (can be {@code null})
176-
* @return result of check
177-
* @throws QueryException query exception
178-
*/
179-
public final boolean equal(final Item item, final Collation coll, final InputInfo ii)
180-
throws QueryException {
181-
return compare(item, coll, false, ii) == 0;
182-
}
183-
184170
/**
185171
* Compares items for deep equality.
186172
* Called by {@link DeepEqual}.
@@ -201,7 +187,7 @@ public boolean deepEqual(final Item item, final DeepEqual deep) throws QueryExce
201187
* @throws QueryException query exception
202188
*/
203189
public boolean atomicEqual(final Item item) throws QueryException {
204-
return this == item || comparable(item) && equal(item, null, null);
190+
return this == item || comparable(item) && compare(item, null, false, null) == 0;
205191
}
206192

207193
/**

basex-core/src/main/java/org/basex/query/value/item/QNm.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,7 @@ public byte[] string() {
168168

169169
@Override
170170
public boolean deepEqual(final Item item, final DeepEqual deep) throws QueryException {
171-
return type == item.type && equal(item, null, deep.info) && (
172-
!deep.options.get(DeepEqualOptions.NAMESPACE_PREFIXES) ||
171+
return atomicEqual(item) && (!deep.options.get(DeepEqualOptions.NAMESPACE_PREFIXES) ||
173172
Token.eq(prefix(), ((QNm) item).prefix()));
174173
}
175174

basex-core/src/main/java/org/basex/query/value/type/SeqType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ private Item coerceAtom(final Item item, final QueryContext qc, final InputInfo
350350
return null;
351351
}
352352
final Item cast = (Item) cast(item, true, qc, info);
353-
return relabel == null || cast.equal(relabel, null, info) ? cast : null;
353+
return relabel == null || cast.compare(relabel, null, false, info) == 0 ? cast : null;
354354
}
355355

356356
/**

0 commit comments

Comments
 (0)