@itwin/core-backend
Version:
iTwin.js backend components
157 lines • 5.86 kB
JavaScript
import { Logger, LogLevel, StopWatch } from "@itwin/core-bentley";
import { expect } from "chai";
import { ConcurrentQuery } from "../../ConcurrentQuery";
import { SnapshotDb } from "../../IModelDb";
import { _nativeDb } from "../../core-backend";
import { IModelTestUtils } from "../IModelTestUtils";
class LoadSimulator {
db;
scenario;
constructor(db, scenario) {
this.db = db;
this.scenario = scenario;
}
async runQueryTask(reader) {
try {
while (await reader.step()) { }
return { stats: reader.stats };
}
catch (err) {
return { stats: reader.stats, error: err };
}
}
async run() {
ConcurrentQuery.shutdown(this.db[_nativeDb]);
if (this.scenario.config) {
const config = ConcurrentQuery.resetConfig(this.db[_nativeDb], this.scenario.config);
// eslint-disable-next-line no-console
console.log(config);
}
const overallTime = new StopWatch();
overallTime.start();
const results = [];
for (let i = 0; i < this.scenario.totalBatches; ++i) {
const promises = [];
const readerTasks = Array(this.scenario.taskPerBatch).fill(undefined).map(() => this.scenario.createReader(this.db));
readerTasks.forEach((reader) => {
promises.push(this.runQueryTask(reader));
});
results.push(...await Promise.all(promises));
}
overallTime.stop();
const errors = results.filter((x) => x.error !== undefined);
const errorsMap = new Map();
errors.forEach((x) => {
if (x.error instanceof Error) {
if (!errorsMap.has(x.error.message)) {
errorsMap.set(x.error.message, 1);
}
else {
errorsMap.set(x.error.message, errorsMap.get(x.error.message) + 1);
}
}
else {
if (!errorsMap.has("error")) {
errorsMap.set("error", 1);
}
else {
errorsMap.set("error", errorsMap.get("error") + 1);
}
}
});
const errorCount = errors.length;
let backendCpuTime = BigInt(0);
let backendTotalTime = BigInt(0);
let backendMemUsed = BigInt(0);
let backendRowsReturned = BigInt(0);
let totalTime = BigInt(0);
let retryCount = BigInt(0);
let prepareTime = BigInt(0);
// Calculate average
results.forEach((r) => {
backendCpuTime += BigInt(r.stats.backendCpuTime);
backendTotalTime += BigInt(r.stats.backendTotalTime);
backendMemUsed += BigInt(r.stats.backendMemUsed);
backendRowsReturned += BigInt(r.stats.backendRowsReturned);
totalTime += BigInt(r.stats.totalTime);
retryCount += BigInt(r.stats.retryCount);
prepareTime += BigInt(r.stats.prepareTime);
});
backendCpuTime /= BigInt(results.length);
backendTotalTime /= BigInt(results.length);
backendMemUsed /= BigInt(results.length);
backendRowsReturned /= BigInt(results.length);
totalTime /= BigInt(results.length);
retryCount /= BigInt(results.length);
// prepareTime /= BigInt(results.length);
return {
result: {
backendCpuTime,
backendTotalTime,
backendMemUsed,
backendRowsReturned,
totalTime,
retryCount,
prepareTime,
},
overallTimeInSec: overallTime.currentSeconds,
errorCount,
totalQueries: results.length,
errorMap: errorsMap
};
}
}
describe.skip("ConcurrentQueryLoad", () => {
it("should run", async () => {
Logger.initializeToConsole();
Logger.setLevel("ECDb.ConcurrentQuery", LogLevel.Trace);
const scenario = {
name: "ConcurrentQueryLoad",
config: {
globalQuota: { time: 1, memory: 8388608 },
workerThreads: 1,
},
totalBatches: 1,
taskPerBatch: 1,
createReader: (dbs) => {
const queries = [
{
sql: `
WITH sequence(n) AS (
SELECT 1
UNION ALL
SELECT n + 1 FROM sequence WHERE n < 10000000
)
SELECT COUNT(*)
FROM bis.SpatialIndex i, sequence s
WHERE i.ECInstanceId MATCH iModel_spatial_overlap_aabb(
iModel_bbox(random(), random(), random(), random(),random(), random()))`
},
{
sql: `
WITH sequence(n) AS (
SELECT 1
UNION ALL
SELECT n + 1 FROM sequence WHERE n < 10000000
)
SELECT COUNT(*) FROM sequence`
},
{
sql: "SELECT $ FROM bis.Element LIMIT 10000"
}
];
const idx = Math.floor(Math.random() * queries.length);
return dbs.createQueryReader(queries[idx].sql);
}
};
const verySmallFile = IModelTestUtils.resolveAssetFile("test.bim");
const db = SnapshotDb.openFile(verySmallFile);
const simulator = new LoadSimulator(db, scenario);
const result = await simulator.run();
// eslint-disable-next-line no-console
console.log(result);
db.close();
expect(result.errorCount).to.be.equal(0);
});
});
//# sourceMappingURL=ConcurrentQueryLoad.test.js.map