Files
mariadb-connector-nodejs/benchmarks/common_benchmarks.js
2018-07-04 11:40:59 +02:00

396 lines
11 KiB
JavaScript

"use strict";
const Benchmark = require("benchmark");
const conf = require("../test/conf");
const colors = require("colors");
const mariadb = require("../promise");
const callbackMariadb = require("../callback");
let promiseMariasql, mariasql, promiseMysql, mysql, promiseMysql2, mysql2;
try {
promiseMysql = require("promise-mysql");
} catch (err) {}
try {
promiseMysql2 = require("mysql2/promise");
} catch (err) {}
try {
promiseMariasql = require("mariasql-promise");
} catch (err) {}
try {
mysql = require("mysql");
} catch (err) {}
try {
mysql2 = require("mysql2");
} catch (err) {}
try {
mariasql = require("mariasql");
} catch (err) {}
function Bench() {
this.dbReady = 0;
this.reportData = {};
this.driverLen = 2;
this.ready = 0;
this.suiteReady = function() {
this.ready++;
if (this.ready === 2) {
this.suite.run();
}
};
const dbReady = function(name, driverLen) {
bench.dbReady++;
console.log("driver for " + name + " connected (" + bench.dbReady + "/" + driverLen + ")");
if (bench.dbReady === driverLen) {
bench.suiteReady();
}
};
const config = conf.baseConfig;
config.charsetNumber = 224;
config.trace = false;
// config.debug = true;
// if (!mariasql && process.platform === "win32") {
// config.socketPath = "\\\\.\\pipe\\MySQL";
// }
console.log(config);
this.CONN = {};
const bench = this;
const connList = this.CONN;
if (promiseMysql) {
this.driverLen++;
connList["PROMISE_MYSQL"] = { desc: "promise-mysql", promise: true };
promiseMysql
.createConnection(config)
.then(conn => {
connList["PROMISE_MYSQL"].drv = conn;
dbReady("promise-mysql", this.driverLen);
})
.catch(err => {
throw err;
});
}
if (mysql) {
this.driverLen++;
connList["MYSQL"] = { desc: "mysql", promise: false };
const conn = mysql.createConnection(config);
conn.connect(err => {
connList["MYSQL"].drv = conn;
conn.on("error", err => console.log("driver mysql error :" + err));
dbReady("mysql", this.driverLen);
});
}
if (mysql2) {
this.driverLen++;
connList["MYSQL2"] = { desc: "mysql2", promise: false };
const conn = mysql2.createConnection(config);
conn.connect(() => {
connList["MYSQL2"].drv = conn;
conn.on("error", err => console.log("driver mysql2 error :" + err));
dbReady("mysql2", this.driverLen);
});
}
if (promiseMysql2) {
this.driverLen++;
connList["PROMISE_MYSQL2"] = { desc: "promise mysql2", promise: true };
promiseMysql2
.createConnection(config)
.then(conn => {
connList["PROMISE_MYSQL2"].drv = conn;
conn.on("error", err => console.log("driver mysql2 promise error :" + err));
dbReady("promise mysql2", this.driverLen);
})
.catch(err => {
throw err;
});
}
const mariaConn = callbackMariadb.createConnection(config);
connList["MARIADB"] = { desc: "mariadb", promise: true };
mariaConn.connect(() => {
connList["MARIADB"].drv = mariaConn;
mariaConn.on("error", err => console.log("driver mariadb error :" + err));
dbReady("mariadb", this.driverLen);
});
connList["PROMISE_MARIADB"] = { desc: "promise mariadb", promise: false };
mariadb
.createConnection(config)
.then(conn => {
connList["PROMISE_MARIADB"].drv = conn;
conn.on("error", err => console.log("driver mariadb promise error :" + err));
dbReady("promise-mariadb", this.driverLen);
})
.catch(err => {
throw err;
});
const configC = Object.assign({}, config);
configC.charset = "utf8mb4";
configC.db = config.database;
configC.metadata = true;
if (config.socketPath != null) {
configC.unixSocket = config.socketPath;
configC.protocol = "socket";
}
if (promiseMariasql) {
this.driverLen++;
connList["PROMISE_MARIASQL"] = { desc: "promise mariasql", promise: false };
promiseMariasql
.createConnection(config)
.then(conn => {
connList["PROMISE_MARIASQL"].drv = conn;
dbReady("promise-mariasql", this.driverLen);
})
.catch(err => {
throw err;
});
}
if (mariasql) {
this.driverLen++;
connList["MARIASQL"] = { desc: "mariasql", drv: conn, promise: true };
const conn = mariasql.createConnection(config);
conn.connect(err => {
connList["MARIASQL"].drv = conn;
dbReady("mariasql", this.driverLen);
});
}
this.initFcts = [];
//200 is a minimum to have benchmark average variation of 1%
this.minSamples = 200;
this.suite = new Benchmark.Suite("foo", {
// called when the suite starts running
onStart: function() {
console.log("start : init test : " + bench.initFcts.length);
for (let i = 0; i < bench.initFcts.length; i++) {
console.log("initializing test data " + (i + 1) + "/" + bench.initFcts.length);
if (bench.initFcts[i]) {
bench.initFcts[i].call(this, bench.CONN.MARIADB.drv);
}
}
console.log("initializing test data done");
},
// called between running benchmarks
onCycle: function(event) {
pingAll(connList);
//to avoid mysql2 taking all the server memory
if (promiseMysql2 && promiseMysql2.clearParserCache) promiseMysql2.clearParserCache();
if (mysql2 && mysql2.clearParserCache) mysql2.clearParserCache();
console.log(event.target.toString());
const drvType = event.target.options.drvType;
const benchTitle =
event.target.options.benchTitle + " ( sql: " + event.target.options.displaySql + " )";
const iteration = 1 / event.target.times.period;
const variation = event.target.stats.rme;
if (!bench.reportData[benchTitle]) {
bench.reportData[benchTitle] = [];
}
if (drvType !== "warmup") {
bench.reportData[benchTitle].push({
drvType: drvType,
iteration: iteration,
variation: variation
});
}
},
// called when the suite completes running
onComplete: function() {
bench.end(bench);
}
});
}
Bench.prototype.end = function(bench) {
console.log("ending connectors");
this.endConnection(this.CONN.MARIADB);
this.endConnection(this.CONN.PROMISE_MARIADB);
if (mysql) this.endConnection(this.CONN.MYSQL);
if (mysql2) this.endConnection(this.CONN.MYSQL2);
if (mariasql) this.endConnection(this.CONN.MARIASQL);
if (promiseMysql) this.endConnection(this.CONN.PROMISE_MYSQL);
if (promiseMysql2) this.endConnection(this.CONN.PROMISE_MYSQL2);
if (promiseMariasql) this.endConnection(this.CONN.PROMISE_MARIASQL);
bench.displayReport();
};
Bench.prototype.endConnection = function(conn) {
try {
//using destroy, because MySQL driver fail when using end() for windows named pipe
conn.drv.destroy();
} catch (err) {
console.log("ending error for connection '" + conn.desc + "'");
console.log(err);
}
};
Bench.prototype.displayReport = function() {
const simpleFormat = new Intl.NumberFormat("en-EN", {
maximumFractionDigits: 1
});
const simpleFormatPerc = new Intl.NumberFormat("en-EN", {
style: "percent",
maximumFractionDigits: 1
});
console.log("");
console.log("");
console.log("--- BENCHMARK RESULTS ---".yellow);
console.log(
"/* travis bench are not to take as is, because VM might run some other testing script that can change results */"
.gray
);
const keys = Object.keys(this.reportData);
for (let i = 0; i < keys.length; i++) {
let base = 0;
let best = 0;
let data = this.reportData[keys[i]];
for (let j = 0; j < data.length; j++) {
let o = data[j];
if (o.drvType === "mysql" || o.drvType === "promise-mysql") {
base = o.iteration;
}
if (o.iteration > best) {
best = o.iteration;
}
}
//display results
console.log("");
console.log("bench : " + keys[i]);
for (let j = 0; j < data.length; j++) {
let o = data[j];
const val = (100 * (o.iteration - base)) / base;
const perc = simpleFormat.format(val);
const tt =
" " +
this.fill(o.drvType, 10) +
" : " +
this.fill(simpleFormat.format(o.iteration), 8, false) +
" ops/s " +
//'±' +this.fill(simpleFormat.format(o.variation), 6, false) + '%' +
(o.iteration === base
? ""
: " ( " + this.fill((val > 0 ? "+" : "") + perc, 6, false) + "% )");
if (o.drvType.includes("mariadb")) {
if (o.iteration < best) {
console.log(tt.red);
} else {
console.log(tt.green);
}
} else {
console.log(tt);
}
}
}
};
Bench.prototype.fill = function(val, length, right) {
if (right) {
while (val.length < length) {
val += " ";
}
} else {
while (val.length < length) {
val = " " + val;
}
}
return val;
};
Bench.prototype.add = function(title, displaySql, fct, onComplete, isPromise, conn) {
const self = this;
const addTest = getAddTest(self, this.suite, fct, this.minSamples, title, displaySql, onComplete);
if (conn) {
addTest(conn, conn.desc);
} else {
if (isPromise) {
addTest(self.CONN.PROMISE_MARIADB, "warmup");
} else {
addTest(self.CONN.MARIADB, "warmup");
}
if (!isPromise && mysql) {
addTest(self.CONN.MYSQL, self.CONN.MYSQL.desc);
}
if (isPromise && promiseMysql) {
addTest(self.CONN.PROMISE_MYSQL, self.CONN.PROMISE_MYSQL.desc);
}
if (!isPromise && mysql2) {
addTest(self.CONN.MYSQL2, self.CONN.MYSQL2.desc);
}
if (isPromise && promiseMysql2) {
addTest(self.CONN.PROMISE_MYSQL2, self.CONN.PROMISE_MYSQL2.desc);
}
if (isPromise) {
addTest(self.CONN.PROMISE_MARIADB, self.CONN.PROMISE_MARIADB.desc);
} else {
addTest(self.CONN.MARIADB, self.CONN.MARIADB.desc);
}
if (isPromise && promiseMariasql) {
addTest(self.CONN.PROMISE_MARIASQL, self.CONN.PROMISE_MARIASQL.desc);
}
if (!isPromise && mariasql) {
addTest(self.CONN.MARIASQL, self.CONN.MARIASQL.desc);
}
}
};
const getAddTest = function(self, suite, fct, minSamples, title, displaySql, onComplete) {
return function(conn, name) {
suite.add({
name: title + " - " + name,
fn: function(deferred) {
fct.call(self, conn.drv, deferred);
},
onComplete: () => {
if (onComplete) onComplete.call(self, conn.drv);
},
minSamples: minSamples,
defer: true,
drvType: name,
benchTitle: title,
displaySql: displaySql
});
};
};
const pingAll = function(conns) {
let keys = Object.keys(conns);
for (let k = 0; k < keys.length; ++k) {
conns[keys[k]].drv.ping();
}
};
module.exports = Bench;