Skip to content

Commit 3434c7e

Browse files
committed
init: benchmarks
1 parent 233f0bc commit 3434c7e

File tree

8 files changed

+208
-17
lines changed

8 files changed

+208
-17
lines changed

bench/index.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { parseQuery, parseQueryEXP } from '../src/parse'
2+
3+
const queries = [
4+
' What song was or do you want to be the your first dance at your wedding',
5+
'What song would make the best theme music for you',
6+
'What is the most irrational superstition you have',
7+
'What is "the weirdest food" combination "you enjoy"',
8+
'What is the stupidest thing you ever did on a dare',
9+
'What is the worst date you have ever been on',
10+
'Who is the most embarrassing person you had a crush on',
11+
'What is your idea of the "perfect day"',
12+
'If you could swap lives with one of your friends, who would it be',
13+
'Who knows the most secrets about you',
14+
// 'What are your must-have qualities in a best friend',
15+
// 'If you had to get a tattoo today, what would you get',
16+
// 'If you could have free meals for life at one fast food chain, which one would you choose',
17+
// 'What is the most embarrassing thing your parents have ever done',
18+
// 'What is a lie or exaggeration you said to impress a crush',
19+
// 'What is the silliest you have ever felt',
20+
// 'When was the last time you laughed so hard that you cried',
21+
// 'What "does your mother yell at you" when she’s angry',
22+
// 'What is a telltale sign that you are upset',
23+
// 'What is your nickname',
24+
// 'What is the wackiest thing you ever did to help a friend',
25+
// 'What fictional character would you most like to be friends with',
26+
// 'What is your favorite topic to talk about',
27+
]
28+
29+
function benchIter(fn, iterations = 1) {
30+
const start = new Date().valueOf()
31+
for (let i = 0; i < iterations; i++) {
32+
fn()
33+
}
34+
console.log(new Date().valueOf() - start)
35+
}
36+
37+
function fun(fn) {
38+
queries.forEach((q, i) => {
39+
fn(q)
40+
})
41+
}
42+
43+
benchIter(() => fun(parseQuery))
44+
benchIter(() => fun(parseQueryEXP))

built/filter.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import { filter } from './lib/structs';
2-
export declare function buildFilters(filters: filter[]): import("arangojs/aql").GeneratedAqlQuery;
1+
import { Filter } from './lib/structs';
2+
export declare function buildFilters(filters: Filter[]): import("arangojs/aql").GeneratedAqlQuery;

built/lib/structs.d.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ export interface query {
1515
/**
1616
* either an array of @param term interfaces or a string to be parsed by `parseQuery()`
1717
* */
18-
terms: term[] | string;
18+
terms: Term[] | string;
1919
/**
2020
* the name(s) of the document key to search. @default "text"
2121
* */
2222
key?: string[] | string;
2323
/**
2424
* a list of @filter interfaces. All filters are implicitly AND'ed together.
2525
* */
26-
filters?: filter[];
26+
filters?: Filter[];
2727
}
2828
/**
2929
* Each collection referenced by the ArangoSearch that the user wishes to
@@ -60,12 +60,12 @@ export interface collection {
6060
* | LEVENS | TODO | TODO| TODO |
6161
* ```
6262
* */
63-
export interface term {
63+
export interface Term {
6464
/**
6565
* must be one of [ 'phr', 'tok' ], corresponding to `PHRASE` and
6666
* `TOKENS` respectively.
6767
**/
68-
type: string;
68+
type: Type;
6969
/**
7070
* the search string
7171
* */
@@ -74,16 +74,35 @@ export interface term {
7474
* must be one of [ '+', '?', '-' ] corresponding to `ANDS`, `ORS`, and
7575
* `NOTS`, respectively.
7676
* */
77-
op: string;
77+
op: Operator;
78+
}
79+
export declare enum Type {
80+
phrase = "phr",
81+
token = "tok"
82+
}
83+
export declare enum Operator {
84+
AND = "+",
85+
'+' = "+",
86+
OR = "?",
87+
'?' = "?",
88+
NOT = "-",
89+
'-' = "-"
7890
}
7991
/**
8092
* passed to AQL `FILTER`
8193
* */
82-
export interface filter {
94+
export interface Filter {
8395
/** the arango document field name to filter on */
8496
field: string;
8597
/** the high-level operator to filter by */
8698
op: string;
8799
/** the query string to filter with */
88100
val: string | number | Date;
89101
}
102+
export declare class Char {
103+
char: string;
104+
constructor(ch: string);
105+
isSpace(): boolean;
106+
isOperator(): boolean;
107+
isQuote(): boolean;
108+
}

built/lib/structs.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,33 @@
11
"use strict";
22
exports.__esModule = true;
3+
exports.Char = exports.Operator = exports.Type = void 0;
4+
var Type;
5+
(function (Type) {
6+
Type["phrase"] = "phr";
7+
Type["token"] = "tok";
8+
})(Type = exports.Type || (exports.Type = {}));
9+
var Operator;
10+
(function (Operator) {
11+
Operator["AND"] = "+";
12+
Operator["+"] = "+";
13+
Operator["OR"] = "?";
14+
Operator["?"] = "?";
15+
Operator["NOT"] = "-";
16+
Operator["-"] = "-";
17+
})(Operator = exports.Operator || (exports.Operator = {}));
18+
var Char = /** @class */ (function () {
19+
function Char(ch) {
20+
this.char = ch;
21+
}
22+
Char.prototype.isSpace = function () {
23+
return /\s/.test(this.char);
24+
};
25+
Char.prototype.isOperator = function () {
26+
return /[-+?]/.test(this.char);
27+
};
28+
Char.prototype.isQuote = function () {
29+
return /"|'/.test(this.char);
30+
};
31+
return Char;
32+
}());
33+
exports.Char = Char;

built/parse.d.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
1-
import { term } from './lib/structs';
2-
export declare function parseQuery(queryString: string): term[];
1+
import { Term } from './lib/structs';
2+
export declare function parseQuery(queryString: string): Term[];
3+
export declare function parseQueryEXP(queryString: string): Term[];
4+
export declare class ParseError extends Error {
5+
char: string;
6+
pos: number;
7+
constructor(char: string, pos: number, message: string);
8+
print(): string;
9+
}

built/parse.js

Lines changed: 94 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,121 @@
11
"use strict";
2+
var __extends = (this && this.__extends) || (function () {
3+
var extendStatics = function (d, b) {
4+
extendStatics = Object.setPrototypeOf ||
5+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7+
return extendStatics(d, b);
8+
};
9+
return function (d, b) {
10+
if (typeof b !== "function" && b !== null)
11+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12+
extendStatics(d, b);
13+
function __() { this.constructor = d; }
14+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15+
};
16+
})();
217
exports.__esModule = true;
3-
exports.parseQuery = void 0;
18+
exports.ParseError = exports.parseQueryEXP = exports.parseQuery = void 0;
19+
var structs_1 = require("./lib/structs");
420
function parseQuery(queryString) {
521
var queryRgx = /[+?-]?(["'(]).+?(\1|\))|[^"'()\s]+/g;
622
var matches = queryString.match(queryRgx);
723
if (!matches)
824
return [];
925
return matches.map(function (match) {
1026
/* strip op */
11-
var op = '?';
27+
var op = structs_1.Operator.OR;
1228
if (/[+?-]/.test(match[0])) {
13-
op = match[0];
29+
op = structs_1.Operator[match[0]];
1430
match = match.substring(1);
1531
}
1632
if (match[0] == '"' || match[0] == "'") {
1733
return {
18-
type: 'phr',
34+
type: structs_1.Type.phrase,
1935
val: match,
2036
op: op
2137
};
2238
}
2339
else {
2440
return {
25-
type: 'tok',
41+
type: structs_1.Type.token,
2642
val: match,
2743
op: op
2844
};
2945
}
3046
});
3147
}
3248
exports.parseQuery = parseQuery;
49+
function parseQueryEXP(queryString) {
50+
return lex(queryString);
51+
}
52+
exports.parseQueryEXP = parseQueryEXP;
53+
function lex(queryString) {
54+
var lexes = [];
55+
var curToken = '';
56+
var curTokenType = structs_1.Type.token;
57+
var curOperator = structs_1.Operator.OR;
58+
var isToken = false;
59+
for (var i = 0; i < queryString.length; i++) {
60+
var ch = new structs_1.Char(queryString[i]);
61+
if (ch.isSpace()) {
62+
if (curToken.length) {
63+
if (curTokenType === structs_1.Type.token) {
64+
isToken = true;
65+
}
66+
else {
67+
curToken += ch.char;
68+
}
69+
}
70+
}
71+
else if (ch.isOperator()) {
72+
if (curToken.length) {
73+
throw new ParseError(ch.char, i, "Logical operator must precede query term.");
74+
}
75+
curOperator = structs_1.Operator[ch.char];
76+
}
77+
else if (ch.isQuote()) {
78+
if (curToken.length && curTokenType === structs_1.Type.phrase) {
79+
isToken = true;
80+
}
81+
else {
82+
curTokenType = structs_1.Type.phrase;
83+
}
84+
}
85+
else {
86+
curToken += ch.char;
87+
}
88+
if (isToken) {
89+
resetCur();
90+
}
91+
}
92+
if (curToken.length) {
93+
resetCur();
94+
}
95+
function resetCur() {
96+
lexes.push({
97+
type: curTokenType,
98+
val: curToken,
99+
op: curOperator
100+
});
101+
curToken = '';
102+
curTokenType = structs_1.Type.token;
103+
curOperator = structs_1.Operator.OR;
104+
isToken = false;
105+
}
106+
return lexes;
107+
}
108+
var ParseError = /** @class */ (function (_super) {
109+
__extends(ParseError, _super);
110+
function ParseError(char, pos, message) {
111+
var _this = _super.call(this, message) || this;
112+
_this.char = char;
113+
_this.pos = pos;
114+
return _this;
115+
}
116+
ParseError.prototype.print = function () {
117+
return "err: \u201C ".concat(this.char, " \u201D in position ").concat(this.pos, " ").concat(this.message);
118+
};
119+
return ParseError;
120+
}(Error));
121+
exports.ParseError = ParseError;

built/search.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cook
66
exports.__esModule = true;
77
exports.buildSearch = void 0;
88
var arangojs_1 = require("arangojs");
9+
var structs_1 = require("./lib/structs");
910
var parse_1 = require("./parse");
1011
function buildSearch(query) {
1112
/* parse string query */
@@ -35,7 +36,7 @@ function buildOps(collections, terms, op) {
3536
if (!queryTerms.length)
3637
return;
3738
/* phrases */
38-
var phrases = queryTerms.filter(function (qT) { return qT.type == 'phr'; });
39+
var phrases = queryTerms.filter(function (qT) { return qT.type == structs_1.Type.phrase; });
3940
phrases = buildPhrases(phrases, collections, opWord);
4041
/* tokens */
4142
var tokens = queryTerms.filter(function (qT) { return qT.type === 'tok'; });

src/lib/structs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export class Char {
120120
return /\s/.test(this.char)
121121
}
122122
isOperator() {
123-
return /[+-?]/.test(this.char)
123+
return /[-+?]/.test(this.char)
124124
}
125125
isQuote() {
126126
return /"|'/.test(this.char)

0 commit comments

Comments
 (0)