Add NodeJs bindings benchmarks (#7004)
This commit is contained in:
committed by
GitHub
parent
7802f86bd6
commit
84f12c7c6d
@@ -0,0 +1,211 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const readline = require('readline');
|
||||
const seedrandom = require('seedrandom');
|
||||
|
||||
|
||||
let RNG;
|
||||
|
||||
class GPSData {
|
||||
constructor(gpsTracesFilePath) {
|
||||
this.tracks = {};
|
||||
this.coordinates = [];
|
||||
this.trackIds = [];
|
||||
this._loadGPSTraces(gpsTracesFilePath);
|
||||
}
|
||||
|
||||
_loadGPSTraces(gpsTracesFilePath) {
|
||||
const expandedPath = path.resolve(gpsTracesFilePath);
|
||||
const data = fs.readFileSync(expandedPath, 'utf-8');
|
||||
const lines = data.split('\n');
|
||||
const headers = lines[0].split(',');
|
||||
|
||||
const latitudeIndex = headers.indexOf('Latitude');
|
||||
const longitudeIndex = headers.indexOf('Longitude');
|
||||
const trackIdIndex = headers.indexOf('TrackID');
|
||||
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
if (lines[i].trim() === '') continue;
|
||||
const row = lines[i].split(',');
|
||||
|
||||
const latitude = parseFloat(row[latitudeIndex]);
|
||||
const longitude = parseFloat(row[longitudeIndex]);
|
||||
const trackId = row[trackIdIndex];
|
||||
|
||||
const coord = [longitude, latitude];
|
||||
this.coordinates.push(coord);
|
||||
|
||||
if (!this.tracks[trackId]) {
|
||||
this.tracks[trackId] = [];
|
||||
}
|
||||
this.tracks[trackId].push(coord);
|
||||
}
|
||||
|
||||
this.trackIds = Object.keys(this.tracks);
|
||||
}
|
||||
|
||||
getRandomCoordinate() {
|
||||
const randomIndex = Math.floor(RNG() * this.coordinates.length);
|
||||
return this.coordinates[randomIndex];
|
||||
}
|
||||
|
||||
getRandomTrack() {
|
||||
const randomIndex = Math.floor(RNG() * this.trackIds.length);
|
||||
const trackId = this.trackIds[randomIndex];
|
||||
return this.tracks[trackId];
|
||||
}
|
||||
};
|
||||
|
||||
async function runOSRMMethod(osrm, method, coordinates) {
|
||||
const time = await new Promise((resolve, reject) => {
|
||||
const startTime = process.hrtime();
|
||||
osrm[method]({coordinates}, (err, result) => {
|
||||
if (err) {
|
||||
if (['NoSegment', 'NoMatch', 'NoRoute', 'NoTrips'].includes(err.message)) {
|
||||
resolve(null);
|
||||
} else {
|
||||
|
||||
reject(err);
|
||||
}
|
||||
} else {
|
||||
const endTime = process.hrtime(startTime);
|
||||
resolve(endTime[0] + endTime[1] / 1e9);
|
||||
}
|
||||
});
|
||||
});
|
||||
return time;
|
||||
}
|
||||
|
||||
async function nearest(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const coord = gpsData.getRandomCoordinate();
|
||||
times.push(await runOSRMMethod(osrm, 'nearest', [coord]));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
async function route(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const from = gpsData.getRandomCoordinate();
|
||||
const to = gpsData.getRandomCoordinate();
|
||||
|
||||
|
||||
times.push(await runOSRMMethod(osrm, 'route', [from, to]));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
async function table(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 250; i++) {
|
||||
const numPoints = Math.floor(RNG() * 3) + 15;
|
||||
const coordinates = [];
|
||||
for (let i = 0; i < numPoints; i++) {
|
||||
coordinates.push(gpsData.getRandomCoordinate());
|
||||
}
|
||||
|
||||
|
||||
times.push(await runOSRMMethod(osrm, 'table', coordinates));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
async function match(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const numPoints = Math.floor(RNG() * 50) + 50;
|
||||
const coordinates = gpsData.getRandomTrack().slice(0, numPoints);
|
||||
|
||||
|
||||
times.push(await runOSRMMethod(osrm, 'match', coordinates));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
async function trip(osrm, gpsData) {
|
||||
const times = [];
|
||||
for (let i = 0; i < 250; i++) {
|
||||
const numPoints = Math.floor(RNG() * 2) + 5;
|
||||
const coordinates = [];
|
||||
for (let i = 0; i < numPoints; i++) {
|
||||
coordinates.push(gpsData.getRandomCoordinate());
|
||||
}
|
||||
|
||||
|
||||
times.push(await runOSRMMethod(osrm, 'trip', coordinates));
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
function bootstrapConfidenceInterval(data, numSamples = 1000, confidenceLevel = 0.95) {
|
||||
let means = [];
|
||||
let dataLength = data.length;
|
||||
|
||||
for (let i = 0; i < numSamples; i++) {
|
||||
let sample = [];
|
||||
for (let j = 0; j < dataLength; j++) {
|
||||
let randomIndex = Math.floor(RNG() * dataLength);
|
||||
sample.push(data[randomIndex]);
|
||||
}
|
||||
let sampleMean = sample.reduce((a, b) => a + b, 0) / sample.length;
|
||||
means.push(sampleMean);
|
||||
}
|
||||
|
||||
means.sort((a, b) => a - b);
|
||||
let lowerBoundIndex = Math.floor((1 - confidenceLevel) / 2 * numSamples);
|
||||
let upperBoundIndex = Math.floor((1 + confidenceLevel) / 2 * numSamples);
|
||||
let mean = means.reduce((a, b) => a + b, 0) / means.length;
|
||||
let lowerBound = means[lowerBoundIndex];
|
||||
let upperBound = means[upperBoundIndex];
|
||||
|
||||
return { mean: mean, lowerBound: lowerBound, upperBound: upperBound };
|
||||
}
|
||||
|
||||
function calculateConfidenceInterval(data) {
|
||||
let { mean, lowerBound, upperBound } = bootstrapConfidenceInterval(data);
|
||||
let bestValue = Math.max(...data);
|
||||
let errorMargin = (upperBound - lowerBound) / 2;
|
||||
|
||||
return { mean, errorMargin, bestValue };
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
const {OSRM} = require(args[0]);
|
||||
const path = args[1];
|
||||
const algorithm = args[2].toUpperCase();
|
||||
const method = args[3];
|
||||
const gpsTracesFilePath = args[4];
|
||||
const iterations = parseInt(args[5]);
|
||||
|
||||
const gpsData = new GPSData(gpsTracesFilePath);
|
||||
const osrm = new OSRM({path, algorithm});
|
||||
|
||||
|
||||
const functions = {
|
||||
route: route,
|
||||
table: table,
|
||||
nearest: nearest,
|
||||
match: match,
|
||||
trip: trip
|
||||
};
|
||||
const func = functions[method];
|
||||
if (!func) {
|
||||
throw new Error('Unknown method');
|
||||
}
|
||||
const allTimes = [];
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
RNG = seedrandom(42);
|
||||
allTimes.push((await func(osrm, gpsData)).filter(t => t !== null));
|
||||
}
|
||||
|
||||
const opsPerSec = allTimes.map(times => times.length / times.reduce((a, b) => a + b, 0));
|
||||
const { mean, errorMargin, bestValue } = calculateConfidenceInterval(opsPerSec);
|
||||
console.log(`Ops: ${mean.toFixed(1)} ± ${errorMargin.toFixed(1)} ops/s. Best: ${bestValue.toFixed(1)} ops/s`);
|
||||
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -53,6 +53,7 @@ function run_benchmarks_for_folder {
|
||||
mkdir -p $RESULTS_FOLDER
|
||||
|
||||
BENCHMARKS_FOLDER="$BINARIES_FOLDER/src/benchmarks"
|
||||
|
||||
echo "Running match-bench MLD"
|
||||
$BENCHMARKS_FOLDER/match-bench "$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/match_mld.bench"
|
||||
echo "Running match-bench CH"
|
||||
@@ -81,6 +82,18 @@ function run_benchmarks_for_folder {
|
||||
echo "Running osrm-contract"
|
||||
measure_peak_ram_and_time "$BINARIES_FOLDER/osrm-contract $FOLDER/data.osrm" "$RESULTS_FOLDER/osrm_contract.bench"
|
||||
|
||||
|
||||
for ALGORITHM in ch mld; do
|
||||
for BENCH in nearest table trip route match; do
|
||||
echo "Running node $BENCH $ALGORITHM"
|
||||
START=$(date +%s.%N)
|
||||
node $SCRIPTS_FOLDER/scripts/ci/bench.js $FOLDER/lib/binding/node_osrm.node $FOLDER/data.osrm $ALGORITHM $BENCH $GPS_TRACES > "$RESULTS_FOLDER/node_${BENCH}_${ALGORITHM}.bench" 5
|
||||
END=$(date +%s.%N)
|
||||
DIFF=$(echo "$END - $START" | bc)
|
||||
echo "Took: ${DIFF}s"
|
||||
done
|
||||
done
|
||||
|
||||
for ALGORITHM in ch mld; do
|
||||
for BENCH in nearest table trip route match; do
|
||||
echo "Running random $BENCH $ALGORITHM"
|
||||
|
||||
Reference in New Issue
Block a user