diff --git a/simple/run-small-indexes.js b/simple/run-small-indexes.js new file mode 100644 index 0000000..999f382 --- /dev/null +++ b/simple/run-small-indexes.js @@ -0,0 +1,10 @@ +function main () { + require("./simple/test").test({ + outputCsv: true, + small: true, + indexes: true + }); +} +if (typeof arango !== "undefined") { + main(); +} diff --git a/simple/test.js b/simple/test.js index 1aad5d7..e44536d 100644 --- a/simple/test.js +++ b/simple/test.js @@ -1,3 +1,5 @@ +/* jshint globalstrict:false, strict:false, maxlen: 500 */ +/* global aql, GLOBAL, makeGraph, makeTree, */ "use strict"; const internal = require("internal"); const arango = internal.arango; @@ -96,7 +98,7 @@ function toAsciiTable (title, out) { return table.toString(); } - +let randomPoint; exports.test = function (testParams) { testParams.tiny = testParams.tiny || false; testParams.small = testParams.small || false; @@ -135,7 +137,7 @@ exports.test = function (testParams) { // Substring first 5 characters to limit to A.B.C format and not use any `nightly`, `rc`, `preview` etc. const serverVersion = (((typeof arango) !== "undefined") ? arango.getVersion() : internal.version).split("-")[0]; - testParams.zkdMdiRenamed = semver.satisfies(serverVersion, ">3.11.99") ; + testParams.zkdMdiRenamed = semver.satisfies(serverVersion, ">3.11.99"); const isEnterprise = internal.isEnterprise(); const isCluster = internal.isCluster(); @@ -214,14 +216,14 @@ exports.test = function (testParams) { let errors = []; for (let i = 0; i < tests.length; ++i) { let test = tests[i]; - print(test) + print(test); try { - if (!(test['version'] === undefined || semver.satisfies(serverVersion, test['version']))) { - print(`skipping test ${test['name']}, requires version ${test['version']}`); - } else if (test['legacy'] && !testParams.legacy) { - print(`skipping legacy test ${test['name']}`); + if (!(test["version"] === undefined || semver.satisfies(serverVersion, test["version"]))) { + print(`skipping test ${test["name"]}, requires version ${test["version"]}`); + } else if (test["legacy"] && !testParams.legacy) { + print(`skipping legacy test ${test["name"]}`); } else { - print(`running test ${test['name']}`); + print(`running test ${test["name"]}`); for (let j = 0; j < options.collections.length; ++j) { let collection = options.collections[j]; @@ -231,7 +233,7 @@ exports.test = function (testParams) { const stats = calc(results, options); const result = { - name: test['name'], + name: test["name"], runs: options.runs, min: stats.min.toFixed(options.digits), max: stats.max.toFixed(options.digits), @@ -253,8 +255,8 @@ exports.test = function (testParams) { } // for j } } catch (ex) { - print(`exception in test ${test['name']}: ${String(ex)}\n${String(ex.stack)}`); - errors.push({ name: test['name'], error: ex }); + print(`exception in test ${test["name"]}: ${String(ex)}\n${String(ex.stack)}`); + errors.push({ name: test["name"], error: ex }); GLOBAL.returnValue = 1; } } // for i @@ -810,7 +812,6 @@ exports.test = function (testParams) { createArangoSearch(viewParams); } }, - fill = function (params) { let c = db._collection(params.collection), n = parseInt(params.collection.replace(/[a-z]+/g, ""), 10), @@ -819,6 +820,26 @@ exports.test = function (testParams) { for (let i = 0; i < docSize; ++i) { doc["value" + i] = i; } + const seed = 12132390894; + const randomNumberGeneratorFloat = function (seed) { + const rng = (function *(seed) { + while (true) { + const nextVal = Math.cos(seed++); + yield nextVal; + } + })(seed); + + return function () { + return rng.next().value; + }; + }; + let getVector = function () { + let gen = randomNumberGeneratorFloat(seed); + + return Array.from({ + length: params.dimension + }, () => gen()); + }; const batchSize = params.batchSize; if (batchSize) { @@ -826,7 +847,14 @@ exports.test = function (testParams) { for (let i = 0; i < n / batchSize; ++i) { let docs = []; for (let j = 0; j < batchSize; ++j) { - docs.push({ _key: "test" + (i * batchSize + j), ...doc }); + let oneDoc = { _key: "test" + (i * batchSize + j), ...doc }; + if (params.type === "vector") { + oneDoc["vector"] = getVector(); + if (n / 2 === i) { + randomPoint = oneDoc["vector"]; + } + } + docs.push(oneDoc); } c.insert(docs); } @@ -834,11 +862,17 @@ exports.test = function (testParams) { // perform single document operations for (let i = 0; i < n; ++i) { doc._key = "test" + i; + if (params.type === "vector") { + doc["vector"] = getVector(); + if (n / 2 === i) { + randomPoint = doc["vector"]; + } + } c.insert(doc); } } }, - + // ///////////////////////////////////////////////////////////////////////////// // indexes tests // ///////////////////////////////////////////////////////////////////////////// @@ -846,7 +880,7 @@ exports.test = function (testParams) { insertIndexOne = function (params) { let c = db._collection(params.collection), n = parseInt(params.collection.replace(/[a-z]+/g, ""), 10); - + // perform small batch document operations const batchSize = params.batchSize || 100; let docs = []; @@ -868,11 +902,11 @@ exports.test = function (testParams) { } } }, - + insertIndexTwo = function (params) { let c = db._collection(params.collection), n = parseInt(params.collection.replace(/[a-z]+/g, ""), 10); - + // perform small batch document operations const batchSize = params.batchSize || 100; let docs = []; @@ -1002,10 +1036,10 @@ exports.test = function (testParams) { // edgeTests // ///////////////////////////////////////////////////////////////////////////// - traversalProjections = function(params) { + traversalProjections = function () { // Note that depth 8 is good for all three sizes small (6), medium (7) // and big (8). Depending on the size, we create a different tree. - db._query(`FOR v IN 0..8 OUTBOUND "TreeV/S1:K1" GRAPH "Tree" RETURN v.data`, {}, {}, {silent}); + db._query("FOR v IN 0..8 OUTBOUND \"TreeV/S1:K1\" GRAPH \"Tree\" RETURN v.data", {}, {}, {silent}); }, outbound = function (params) { @@ -2390,7 +2424,7 @@ exports.test = function (testParams) { setup: function (params) { drop(params); create(params); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"] }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"] }); }, type: "number", teardown: drop @@ -2403,7 +2437,7 @@ exports.test = function (testParams) { setup: function (params) { drop(params); create(params); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"], estimates: false }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"], estimates: false }); }, type: "number", teardown: drop @@ -2416,7 +2450,7 @@ exports.test = function (testParams) { setup: function (params) { drop(params); create(params); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"] }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"] }); }, type: "string", teardown: drop @@ -2429,7 +2463,7 @@ exports.test = function (testParams) { setup: function (params) { drop(params); create(params); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"], estimates: false }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"], estimates: false }); }, type: "string", teardown: drop @@ -2442,8 +2476,8 @@ exports.test = function (testParams) { setup: function (params) { drop(params); create(params); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"] }); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value2"] }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"] }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value2"] }); }, type: "number", teardown: drop @@ -2456,8 +2490,8 @@ exports.test = function (testParams) { setup: function (params) { drop(params); create(params); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"], estimates: false }); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value2"], estimates: false }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"], estimates: false }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value2"], estimates: false }); }, type: "number", teardown: drop @@ -2470,8 +2504,8 @@ exports.test = function (testParams) { setup: function (params) { drop(params); create(params); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"] }); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value2"] }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"] }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value2"] }); }, type: "string", teardown: drop @@ -2484,13 +2518,44 @@ exports.test = function (testParams) { setup: function (params) { drop(params); create(params); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"], estimates: false }); - db[params.collection].ensureIndex({ type: "persistent", fields: ["value2"], estimates: false }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value1"], estimates: false }); + db[params.collection].ensureIndex({ type: "persistent", fields: ["value2"], estimates: false }); }, type: "string", teardown: drop } }, + { + name: "indexes-vector", + params: { + vector: true, + dimension: 500, + setup: function (params) { + drop(params); + create(params); + fill(params); + db[params.collection].ensureIndex({ + name: "vector_l2", + type: "vector", + fields: ["vector"], + inBackground: false, + params: { + metric: "l2", + dimension: params.dimension, + nLists: 10, + trainingIterations: 10 + } + }); + }, + func: function (params) { + db._query(aql`FOR d IN + ${db[params.collection]} + SORT APPROX_NEAR_L2(d.vector, ${randomPoint}) LIMIT 5 RETURN {key: d._key}`).toArray(); + }, + type: "vector", + teardown: drop + } + } ]; // Tests without collections/IO, to focus on aql block performance. @@ -2549,7 +2614,7 @@ exports.test = function (testParams) { { name: "traversal-projections", params: { func: traversalProjections } - }, + }, { name: "traversal-outbound-1", params: { func: outbound, minDepth: 1, maxDepth: 1, loops: 1000 } @@ -3276,7 +3341,7 @@ exports.test = function (testParams) { } db._query( params.queryString, - bindParam, + bindParam ); } @@ -3330,7 +3395,7 @@ exports.test = function (testParams) { FILTER d.x == 9 and d.y >= 52 RETURN d` } - }, + } ]; const runSatelliteGraphTests = (testParams.satelliteGraphTests && isEnterprise && isCluster); @@ -3414,7 +3479,7 @@ exports.test = function (testParams) { setup: function (params) { db._drop(params.collection); let col = db._create(params.collection); - let type = (testParams.zkdMdiRenamed) ? "mdi":"zkd"; + let type = (testParams.zkdMdiRenamed) ? "mdi" : "zkd"; col.ensureIndex({type: type, name: "mdiIndex", fields: ["x", "y"], fieldValueTypes: "double"}); db._query(` FOR i IN 0..${params.collectionSize} @@ -3586,7 +3651,7 @@ exports.test = function (testParams) { runTestSuite("Arango Search No Materialization", arangosearchNoMaterializationTests, options); } - + // indexes tests if (testParams.indexes) { options = {