Skip to content

Commit 37d485f

Browse files
[MOD] Token: Optimizations (JDK11+)
1 parent 662ca9b commit 37d485f

File tree

8 files changed

+107
-102
lines changed

8 files changed

+107
-102
lines changed

basex-core/src/main/java/org/basex/query/expr/ft/FTWildcard.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ private boolean parse(final byte[] token) {
7474
boolean f = false;
7575
while(true) {
7676
c = ++i < il ? input[i] : 0;
77-
if(digit(c)) mn = (mn << 3) + (mn << 1) + c - '0';
77+
if(digit(c)) mn = mn * 10 + c - '0';
7878
else if(f && c == ',') break;
7979
else return false;
8080
f = true;
8181
}
8282
f = false;
8383
while(true) {
8484
c = ++i < il ? input[i] : 0;
85-
if(digit(c)) mx = (mx << 3) + (mx << 1) + c - '0';
85+
if(digit(c)) mx = mx * 10 + c - '0';
8686
else if(f && c == '}') break;
8787
else return false;
8888
f = true;

basex-core/src/main/java/org/basex/query/util/ft/FTStringMatch.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ public int compareTo(final FTStringMatch sm) {
4747

4848
@Override
4949
public int hashCode() {
50-
final int h = start + 1;
51-
return (h << 5) - h + end;
50+
return (start + 1) * 31 + end;
5251
}
5352

5453
@Override

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ public boolean deepEqual(final Item item, final DeepEqual deep) throws QueryExce
7676
@Override
7777
public int compare(final Item item, final Collation coll, final boolean transitive,
7878
final InputInfo ii) throws QueryException {
79-
return comparable(item) ? Token.compare(value, item.string(ii), Collation.get(coll, ii)) :
79+
return item.type.isStringOrUntyped() ?
80+
Token.compare(value, item.string(ii), Collation.get(coll, ii)) :
8081
-item.compare(this, coll, transitive, ii);
8182
}
8283

basex-core/src/main/java/org/basex/query/value/node/ANode.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ public final boolean comparable(final Item item) {
103103
@Override
104104
public final int compare(final Item item, final Collation coll, final boolean transitive,
105105
final InputInfo ii) throws QueryException {
106-
return item.type.isStringOrUntyped()
107-
? Token.compare(string(), item.string(ii), Collation.get(coll, ii))
108-
: -item.compare(this, coll, transitive, ii);
106+
return item.type.isStringOrUntyped() ?
107+
Token.compare(string(), item.string(ii), Collation.get(coll, ii)) :
108+
-item.compare(this, coll, transitive, ii);
109109
}
110110

111111
@Override

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,9 @@ public boolean nsSensitive() {
178178

179179
@Override
180180
public int hashCode() {
181-
int h = 0;
181+
int h = 1;
182182
for(final byte[] v : values) {
183-
h = (h << 5) - h + Token.hashCode(v);
183+
h = h * 31 + Token.hashCode(v);
184184
}
185185
return h;
186186
}

basex-core/src/main/java/org/basex/util/Inline.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public static long packInt(final byte[] token) {
8585

8686
long value = 0;
8787
for(final byte b : token) {
88-
value = (value << 3) + (value << 1) + b - '0';
88+
value = value * 10 + b - '0';
8989
// skip conversion if byte is no digit, or if number is too large
9090
if(b < '0' || b > '9' || value > Integer.MAX_VALUE) return -1;
9191
}

basex-core/src/main/java/org/basex/util/Token.java

Lines changed: 85 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ public static byte[] token(final String string) {
168168
*/
169169
public static byte[][] tokens(final String... strings) {
170170
final int sl = strings.length;
171-
final byte[][] tokens = new byte[sl][];
172-
for(int s = 0; s < sl; ++s) tokens[s] = token(strings[s]);
173-
return tokens;
171+
final byte[][] tmp = new byte[sl][];
172+
for(int s = 0; s < sl; ++s) tmp[s] = token(strings[s]);
173+
return tmp;
174174
}
175175

176176
/**
@@ -363,21 +363,21 @@ public static byte[] token(final int integer) {
363363
if(m) n = -n;
364364
int nl = numDigits(n);
365365
if(m) ++nl;
366-
final byte[] num = new byte[nl];
366+
final byte[] tmp = new byte[nl];
367367

368368
// faster division by 10 for values < 81920 (see Integer.getChars)
369369
while(n > 81919) {
370370
final int q = n / 10;
371-
num[--nl] = (byte) (n - (q << 3) - (q << 1) + '0');
371+
tmp[--nl] = (byte) (n - q * 10 + '0');
372372
n = q;
373373
}
374374
while(n != 0) {
375375
final int q = n * 52429 >>> 19;
376-
num[--nl] = (byte) (n - (q << 3) - (q << 1) + '0');
376+
tmp[--nl] = (byte) (n - q * 10 + '0');
377377
n = q;
378378
}
379-
if(m) num[--nl] = '-';
380-
return num;
379+
if(m) tmp[--nl] = '-';
380+
return tmp;
381381
}
382382

383383
/**
@@ -390,15 +390,15 @@ public static byte[] token(final long value, final int radix) {
390390
// use fast variant for powers of two
391391
for(int shift = 1, p = 2; shift < 6; shift++, p <<= 1) {
392392
if(radix == p) {
393-
final byte[] bytes = new byte[(64 + shift - 1) / shift];
393+
final byte[] tmp = new byte[(64 + shift - 1) / shift];
394394
final int mask = (1 << shift) - 1;
395395
long n = value;
396-
int pos = bytes.length;
396+
int pos = tmp.length;
397397
do {
398-
bytes[--pos] = DIGITS[(int) (n & mask)];
398+
tmp[--pos] = DIGITS[(int) (n & mask)];
399399
n >>>= shift;
400400
} while(n != 0);
401-
return substring(bytes, pos);
401+
return substring(tmp, pos);
402402
}
403403
}
404404

@@ -623,7 +623,7 @@ public static long toLong(final byte[] token, final int start, final int end) {
623623
final byte b = token[p];
624624
if(b < '0' || b > '9') break;
625625
if(v >= MAX_LONG && (b > '7' || v > MAX_LONG)) return Long.MIN_VALUE;
626-
v = (v << 3) + (v << 1) + b - '0';
626+
v = v * 10 + b - '0';
627627
}
628628
while(p < end && ws(token[p])) ++p;
629629
return p < end ? Long.MIN_VALUE : m ? -v : v;
@@ -659,7 +659,7 @@ private static int toInt(final byte[] token, final int start, final int end) {
659659
final byte b = token[p];
660660
if(b < '0' || b > '9') break;
661661
if(v >= MAX_INT && (b > '7' || v > MAX_INT)) return Integer.MIN_VALUE;
662-
v = (v << 3) + (v << 1) + b - '0';
662+
v = v * 10 + b - '0';
663663
}
664664
while(p < end && ws(token[p])) ++p;
665665
return p < end || v < 0 ? Integer.MIN_VALUE : m ? -v : v;
@@ -672,9 +672,9 @@ private static int toInt(final byte[] token, final int start, final int end) {
672672
*/
673673
public static int hashCode(final byte[] token) {
674674
final int tl = token.length, s = Math.max(1, tl / MAX_HASH_OPS);
675-
int h = 0;
675+
int h = 1;
676676
for(int t = 0; t < tl; t += s) {
677-
h = (h << 5) - h + token[t];
677+
h = h * 31 + token[t];
678678
}
679679
return h;
680680
}
@@ -737,12 +737,7 @@ public static boolean eq(final byte[] token, final byte[]... tokens) {
737737
* @return result of comparison (-1, 0, 1)
738738
*/
739739
public static int compare(final byte[] token, final byte[] compare) {
740-
final int tl = token.length, cl = compare.length, l = Math.min(tl, cl);
741-
for(int i = 0; i < l; ++i) {
742-
final int c = (token[i] & 0xFF) - (compare[i] & 0xFF);
743-
if(c != 0) return Integer.signum(c);
744-
}
745-
return Integer.signum(tl - cl);
740+
return Integer.signum(Arrays.compareUnsigned(token, compare));
746741
}
747742

748743
/**
@@ -826,7 +821,7 @@ public static int indexOf(final byte[] token, final int ch) {
826821
*/
827822
public static int indexOf(final byte[] token, final int ch, final int pos) {
828823
final int tl = token.length;
829-
if(ch < 0x80) {
824+
if(ch <= 0x7F) {
830825
for(int t = pos; t < tl; t++) {
831826
if(token[t] == ch) return t;
832827
}
@@ -847,7 +842,7 @@ public static int indexOf(final byte[] token, final int ch, final int pos) {
847842
public static int lastIndexOf(final byte[] token, final int ch) {
848843
final int tl = token.length;
849844
int p = -1;
850-
if(ch < 0x80) {
845+
if(ch <= 0x7F) {
851846
for(int t = tl - 1; t >= 0; --t) {
852847
if(token[t] == ch) return t;
853848
}
@@ -882,12 +877,9 @@ public static int indexOf(final byte[] token, final byte[] sub, final int pos) {
882877
final int tl = token.length - sl;
883878
if(pos > tl) return -1;
884879

885-
// compare tokens character wise
886-
for(int t = pos; t <= tl; ++t) {
887-
int s = 0;
888-
while(sub[s] == token[t + s]) {
889-
if(++s == sl) return t;
890-
}
880+
final byte first = sub[0];
881+
for(int t = pos; t <= tl; t++) {
882+
if(token[t] == first && Arrays.mismatch(token, t + 1, t + sl, sub, 1, sl) == -1) return t;
891883
}
892884
return -1;
893885
}
@@ -931,12 +923,8 @@ public static boolean startsWith(final byte[] token, final byte[] sub) {
931923
* @return result of check
932924
*/
933925
public static boolean startsWith(final byte[] token, final byte[] sub, final int pos) {
934-
final int sl = sub.length;
935-
if(sl > token.length - pos) return false;
936-
for(int s = 0, p = pos; s < sl; ++s, ++p) {
937-
if(sub[s] != token[p]) return false;
938-
}
939-
return true;
926+
final int sl = sub.length, tl = token.length;
927+
return sl <= tl - pos && Arrays.mismatch(sub, 0, sl, token, pos, pos + sl) == -1;
940928
}
941929

942930
/**
@@ -956,13 +944,8 @@ public static boolean endsWith(final byte[] token, final int ch) {
956944
* @return result of check
957945
*/
958946
public static boolean endsWith(final byte[] token, final byte[] sub) {
959-
final int sl = sub.length;
960-
final int tl = token.length;
961-
if(sl > tl) return false;
962-
for(int s = sl; s > 0; s--) {
963-
if(sub[sl - s] != token[tl - s]) return false;
964-
}
965-
return true;
947+
final int sl = sub.length, tl = token.length;
948+
return sl <= tl && Arrays.mismatch(sub, 0, sl, token, tl - sl, tl) == -1;
966949
}
967950

968951
/**
@@ -1153,9 +1136,9 @@ public static byte[] concat(final byte[]... tokens) {
11531136
*/
11541137
public static byte[] concat(final Object... objects) {
11551138
final int ol = objects.length;
1156-
final byte[][] tokens = new byte[ol][];
1157-
for(int o = 0; o < ol; o++) tokens[o] = token(objects[o]);
1158-
return concat(tokens);
1139+
final byte[][] tmp = new byte[ol][];
1140+
for(int o = 0; o < ol; o++) tmp[o] = token(objects[o]);
1141+
return concat(tmp);
11591142
}
11601143

11611144
/**
@@ -1165,17 +1148,21 @@ public static byte[] concat(final Object... objects) {
11651148
* @return resulting token
11661149
*/
11671150
public static byte[] delete(final byte[] token, final int ch) {
1168-
// ascii character
11691151
final int tl = token.length;
1170-
if(ch < 0x80) {
1171-
// skip deletion if character is not found
1172-
if(!contains(token, ch)) return token;
1152+
if(ch <= 0x7F) {
1153+
// ascii characters: skip deletion if character is not found
1154+
int c = 0;
1155+
for(final byte b : token) {
1156+
if(b == ch) c++;
1157+
}
1158+
if(c == 0) return token;
11731159

1174-
final TokenBuilder tb = new TokenBuilder(tl);
1160+
final byte[] tmp = new byte[tl - c];
1161+
c = 0;
11751162
for(final byte b : token) {
1176-
if(b != ch) tb.add(b);
1163+
if(b != ch) tmp[c++] = b;
11771164
}
1178-
return tb.finish();
1165+
return tmp;
11791166
}
11801167
// remove character
11811168
final TokenBuilder tb = new TokenBuilder(tl);
@@ -1190,27 +1177,45 @@ public static byte[] delete(final byte[] token, final int ch) {
11901177
*/
11911178
public static byte[] normalize(final byte[] token) {
11921179
final int tl = token.length;
1193-
if(tl == 0) return token;
1194-
final byte[] tmp = new byte[tl];
1180+
int s = 0, e = tl - 1;
1181+
while(s <= e && ws(token[s])) s++;
1182+
while(e > s && ws(token[e])) e--;
1183+
if(s > e) return EMPTY;
1184+
1185+
int size = 0;
1186+
boolean inWs = false, replace = false;
1187+
for(int i = s; i <= e; i++) {
1188+
final byte b = token[i];
1189+
final boolean ws = ws(token[i]);
1190+
if(!(ws && inWs)) {
1191+
size++;
1192+
inWs = ws;
1193+
if(ws && b != ' ') replace = true;
1194+
}
1195+
}
1196+
if(size == tl && !replace) return token;
1197+
1198+
final byte[] tmp = new byte[size];
11951199
int c = 0;
1196-
boolean ws1 = true;
1197-
for(final byte b : token) {
1198-
final boolean ws2 = ws(b);
1199-
if(ws2 && ws1) continue;
1200-
tmp[c++] = ws2 ? (byte) ' ' : b;
1201-
ws1 = ws2;
1200+
inWs = false;
1201+
for(int i = s; i <= e; i++) {
1202+
final byte b = token[i];
1203+
final boolean ws = ws(b);
1204+
if(!(ws && inWs)) {
1205+
tmp[c++] = ws ? (byte) ' ' : b;
1206+
inWs = ws;
1207+
}
12021208
}
1203-
if(c > 0 && ws(tmp[c - 1])) --c;
1204-
return c == tl ? tmp : Arrays.copyOf(tmp, c);
1209+
return tmp;
12051210
}
12061211

12071212
/**
1208-
* Checks if the specified character is a whitespace.
1213+
* Checks if the specified character is a whitespace (0x09, 0x0A, 0x0D, 0x20).
12091214
* @param ch the character to be checked
12101215
* @return result of check
12111216
*/
12121217
public static boolean ws(final int ch) {
1213-
return ch == 0x09 || ch == 0x0A || ch == 0x0D || ch == 0x20;
1218+
return ch >= 0 && ch <= 32 && (1L << ch & 0x100002600L) != 0;
12141219
}
12151220

12161221
/**
@@ -1258,9 +1263,9 @@ public static byte[] uc(final byte[] token) {
12581263
public static byte[] uc(final byte[] token, final boolean ascii) {
12591264
if(ascii) {
12601265
final int tl = token.length;
1261-
final byte[] tok = new byte[tl];
1262-
for(int t = 0; t < tl; t++) tok[t] = (byte) uc(token[t]);
1263-
return tok;
1266+
final byte[] tmp = new byte[tl];
1267+
for(int t = 0; t < tl; t++) tmp[t] = (byte) uc(token[t]);
1268+
return tmp;
12641269
}
12651270
return token(string(token).toUpperCase(Locale.ENGLISH));
12661271
}
@@ -1309,9 +1314,9 @@ public static byte[] lc(final byte[] token) {
13091314
public static byte[] lc(final byte[] token, final boolean ascii) {
13101315
if(ascii) {
13111316
final int tl = token.length;
1312-
final byte[] tok = new byte[tl];
1313-
for(int t = 0; t < tl; t++) tok[t] = (byte) lc(token[t]);
1314-
return tok;
1317+
final byte[] tmp = new byte[tl];
1318+
for(int t = 0; t < tl; t++) tmp[t] = (byte) lc(token[t]);
1319+
return tmp;
13151320
}
13161321
return token(string(token).toLowerCase(Locale.ENGLISH));
13171322
}
@@ -1405,9 +1410,11 @@ public static byte[] encodeUri(final byte[] token, final UriEncoder encoder) {
14051410
* @return hex representation
14061411
*/
14071412
public static byte[] hex(final int value, final int length) {
1408-
final TokenBuilder tb = new TokenBuilder(length);
1409-
for(int l = length - 1; l >= 0; l--) tb.add(HEX_TABLE[value >> (l << 2) & 0xF]);
1410-
return tb.finish();
1413+
final byte[] tmp = new byte[length];
1414+
for(int l = 0; l < length; l++) {
1415+
tmp[length - l - 1] = HEX_TABLE[value >> (l << 2) & 0xF];
1416+
}
1417+
return tmp;
14111418
}
14121419

14131420
/**
@@ -1418,13 +1425,13 @@ public static byte[] hex(final int value, final int length) {
14181425
*/
14191426
public static byte[] hex(final byte[] value, final boolean uc) {
14201427
final int vl = value.length, u = uc ? 0x37 : 0x57;
1421-
final byte[] data = new byte[Array.checkCapacity((long) vl << 1)];
1428+
final byte[] tmp = new byte[Array.checkCapacity((long) vl << 1)];
14221429
for(int v = 0, d = 0; v < vl; v++) {
14231430
final int a = value[v], b = a >> 4 & 0x0F, c = a & 0x0F;
1424-
data[d++] = (byte) (b + (b > 9 ? u : '0'));
1425-
data[d++] = (byte) (c + (c > 9 ? u : '0'));
1431+
tmp[d++] = (byte) (b + (b > 9 ? u : '0'));
1432+
tmp[d++] = (byte) (c + (c > 9 ? u : '0'));
14261433
}
1427-
return data;
1434+
return tmp;
14281435
}
14291436

14301437
/**

0 commit comments

Comments
 (0)