Skip to content

Commit 5826815

Browse files
committed
Added benchmarks for mongodb and mysql
0 parents  commit 5826815

15 files changed

+3557
-0
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.history
2+
node_modules

Diff for: .nvmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v16.17.0

Diff for: benchmark.js

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
const path = require("path");
2+
const { fork } = require("child_process");
3+
const { program } = require("commander");
4+
const autocannon = require("autocannon");
5+
6+
7+
/**
8+
* @param {string} url
9+
* @param {number} connections
10+
* @param {number} duration
11+
*/
12+
async function fire(url, connections, duration) {
13+
const instance = autocannon({
14+
url,
15+
connections,
16+
duration,
17+
headers: {
18+
"Content-Type": "application/json"
19+
},
20+
body: "{}",
21+
title: "benchmark"
22+
});
23+
24+
autocannon.track(instance, {
25+
renderProgressBar: true
26+
});
27+
28+
return instance;
29+
}
30+
31+
function runServerWithMongo() {
32+
return fork(path.join(__dirname, "mongo", "server.js"));
33+
}
34+
35+
function runServerWithMySql() {
36+
return fork(path.join(__dirname, "mysql", "server.js"));
37+
}
38+
39+
/**
40+
* @param {string} type
41+
*/
42+
async function runBenchmark(type) {
43+
console.log(`Running benchmark for ${type}...`);
44+
45+
console.log("Starting server...");
46+
const server = type === "mongo" ? runServerWithMongo() : runServerWithMySql();
47+
48+
await new Promise((resolve) => {
49+
server.on("message", (message) => {
50+
if (message === "ready") {
51+
resolve();
52+
}
53+
});
54+
});
55+
56+
console.log("Starting benchmark...");
57+
58+
const tests = [{
59+
connections: 10,
60+
duration: 30
61+
}, {
62+
connections: 50,
63+
duration: 20
64+
}, {
65+
connections: 100,
66+
duration: 10
67+
}];
68+
69+
const url = `http://localhost:3000/product`;
70+
for (const test of tests) {
71+
const { connections, duration } = test;
72+
console.log(`Connections: ${connections}, Duration: ${duration}s`);
73+
const instance = await fire(url, connections, duration);
74+
}
75+
76+
server.kill("SIGINT");
77+
process.exit(0);
78+
}
79+
80+
program
81+
.command("mongo")
82+
.description("Benchmark mongo")
83+
.action(() => runBenchmark("mongo"));
84+
85+
program
86+
.command("mysql")
87+
.description("Benchmark mysql")
88+
.action(() => runBenchmark("mysql"));
89+
90+
program.parse(process.argv);
91+

Diff for: dataset/index.js

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
const { faker } = require('@faker-js/faker');
2+
3+
faker.seed(123);
4+
5+
/**
6+
* @param {number} product_id
7+
*/
8+
function createDataset(product_id) {
9+
faker.setLocale(faker.random.locale())
10+
11+
return {
12+
product_id: product_id,
13+
created_at: faker.date.past(),
14+
updated_at: faker.date.recent(),
15+
16+
sku: faker.datatype.number({ min: 1, max: 10 }),
17+
upc: faker.datatype.number({ min: 1, max: 10 }),
18+
ean: faker.datatype.number({ min: 1, max: 10 }),
19+
asin: faker.datatype.number({ min: 1, max: 10 }),
20+
gtin: faker.datatype.number({ min: 1, max: 10 }),
21+
mpn: faker.datatype.number({ min: 1, max: 10 }),
22+
23+
24+
age_restriction: faker.datatype.number({ min: 18, max: 99 }),
25+
product: faker.commerce.product(),
26+
name: faker.commerce.productName(),
27+
description: faker.commerce.productDescription(),
28+
adjective: faker.commerce.productAdjective(),
29+
30+
color: faker.color.human(),
31+
material: faker.commerce.productMaterial(),
32+
image_url: faker.image.avatar(),
33+
34+
pallet_length: faker.datatype.number({ min: 1, max: 10 }),
35+
pallet_width: faker.datatype.number({ min: 1, max: 10 }),
36+
pallet_height: faker.datatype.number({ min: 1, max: 10 }),
37+
pallet_weight: faker.datatype.number({ min: 1, max: 10 }),
38+
pallet_quantity: faker.datatype.number({ min: 1, max: 10 }),
39+
40+
box_length: faker.datatype.number({ min: 1, max: 10 }),
41+
box_width: faker.datatype.number({ min: 1, max: 10 }),
42+
box_height: faker.datatype.number({ min: 1, max: 10 }),
43+
box_weight: faker.datatype.number({ min: 1, max: 10 }),
44+
box_quantity: faker.datatype.number({ min: 1, max: 10 }),
45+
46+
item_length: faker.datatype.number({ min: 1, max: 10 }),
47+
item_width: faker.datatype.number({ min: 1, max: 10 }),
48+
item_height: faker.datatype.number({ min: 1, max: 10 }),
49+
item_weight: faker.datatype.number({ min: 1, max: 10 }),
50+
item_quantity: faker.datatype.number({ min: 1, max: 10 }),
51+
52+
price: faker.commerce.price(),
53+
currency: faker.finance.currencyCode(),
54+
currency_symbol: faker.finance.currencySymbol(),
55+
currency_name: faker.finance.currencyName(),
56+
price_tag: faker.finance.amount(),
57+
price_margin: faker.finance.amount(),
58+
price_discount: faker.finance.amount(),
59+
price_tax: faker.finance.amount(),
60+
price_shipping: faker.finance.amount(),
61+
price_shipping_tax: faker.finance.amount(),
62+
price_total: faker.finance.amount(),
63+
64+
department: faker.commerce.department(),
65+
email: faker.internet.email(),
66+
phone: faker.phone.number(),
67+
address: faker.address.street(),
68+
company: faker.company.name(),
69+
city: faker.address.city(),
70+
state: faker.address.state(),
71+
country: faker.address.country(),
72+
zip: faker.address.zipCode(),
73+
74+
ram_size: faker.datatype.number({ min: 1, max: 10 }),
75+
ram_type: faker.datatype.number({ min: 1, max: 10 }),
76+
ram_speed: faker.datatype.number({ min: 1, max: 10 }),
77+
ram_ecc: faker.datatype.number({ min: 1, max: 10 }),
78+
ram_registered: faker.datatype.number({ min: 1, max: 10 }),
79+
ram_latency: faker.datatype.number({ min: 1, max: 10 }),
80+
ram_voltage: faker.datatype.number({ min: 1, max: 10 }),
81+
ram_heat_spreader: faker.datatype.number({ min: 1, max: 10 }),
82+
ram_color: faker.datatype.number({ min: 1, max: 10 }),
83+
ram_module: faker.datatype.number({ min: 1, max: 10 }),
84+
85+
fan_rpm: faker.datatype.number({ min: 1, max: 10 }),
86+
fan_airflow: faker.datatype.number({ min: 1, max: 10 }),
87+
fan_noise: faker.datatype.number({ min: 1, max: 10 }),
88+
fan_color: faker.datatype.number({ min: 1, max: 10 }),
89+
fan_led: faker.datatype.number({ min: 1, max: 10 }),
90+
fan_pump: faker.datatype.number({ min: 1, max: 10 }),
91+
fan_radiator: faker.datatype.number({ min: 1, max: 10 }),
92+
fan_cooler: faker.datatype.number({ min: 1, max: 10 }),
93+
fan_cooler_type: faker.datatype.number({ min: 1, max: 10 }),
94+
fan_cooler_socket: faker.datatype.number({ min: 1, max: 10 }),
95+
96+
manufacturer: faker.company.name(),
97+
model: faker.commerce.productName(),
98+
serial: faker.datatype.number({ min: 1, max: 10 }),
99+
part_number: faker.datatype.number({ min: 1, max: 10 }),
100+
101+
is_active: faker.datatype.boolean(),
102+
is_featured: faker.datatype.boolean(),
103+
is_new: faker.datatype.boolean(),
104+
is_hot: faker.datatype.boolean(),
105+
is_sold: faker.datatype.boolean(),
106+
is_available: faker.datatype.boolean(),
107+
is_preorder: faker.datatype.boolean(),
108+
is_out_of_stock: faker.datatype.boolean(),
109+
is_in_stock: faker.datatype.boolean(),
110+
is_backorder: faker.datatype.boolean(),
111+
is_virtual: faker.datatype.boolean(),
112+
};
113+
}
114+
115+
module.exports = {
116+
createDataset,
117+
};

Diff for: mongo/bootstrap.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const { MongoClient } = require('mongodb');
2+
const lodash = require('lodash');
3+
4+
const { createDataset } = require('../dataset/index.js');
5+
6+
const uri = 'mongodb://localhost:27017';
7+
8+
const client = new MongoClient(uri, {
9+
auth: {
10+
password: 'admin',
11+
username: 'admin',
12+
}
13+
});
14+
15+
async function run() {
16+
try {
17+
await client.connect();
18+
19+
const database = client.db('product');
20+
const collection = database.collection('product');
21+
22+
// this option prevents additional documents from being inserted if one fails
23+
const options = { ordered: true };
24+
25+
const time = Date.now();
26+
27+
let id = 0;
28+
for (let i = 0; i < 100; i++) {
29+
const products = lodash.times(1000, () => createDataset(++id));
30+
await collection.insertMany(products, options);
31+
console.log(`Inserted ${id} products`);
32+
}
33+
34+
console.log(`Inserted ${id} products in ${Date.now() - time}ms`);
35+
36+
} finally {
37+
await client.close();
38+
}
39+
40+
41+
}
42+
43+
run().catch(console.dir);
44+

Diff for: mongo/docker-compose.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: '3.1'
2+
services:
3+
mongo-container:
4+
image: mongo:latest
5+
environment:
6+
- MONGO_INITDB_ROOT_USERNAME=admin
7+
- MONGO_INITDB_ROOT_PASSWORD=admin
8+
ports:
9+
- "27017:27017"
10+
command: mongod

Diff for: mongo/server.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
const { fastify } = require('fastify');
2+
3+
const { MongoClient } = require('mongodb');
4+
const { faker } = require('@faker-js/faker');
5+
6+
const uri = 'mongodb://admin:admin@localhost:27017/?maxPoolSize=20&w=majority';
7+
8+
const client = new MongoClient(uri, {
9+
connectTimeoutMS: 500000,
10+
});
11+
12+
faker.seed(123);
13+
14+
15+
async function run() {
16+
try {
17+
const app = fastify({ logger: false });
18+
19+
const connection = await client.connect();
20+
const database = connection.db('product');
21+
const collection = database.collection('product');
22+
23+
app.get('/product', async (request, reply) => {
24+
const productId = faker.datatype.number({ min: 1, max: 100000 });
25+
26+
const cursor = collection.find({
27+
product_id: productId
28+
});
29+
const products = await cursor.toArray();
30+
31+
return products;
32+
});
33+
34+
app.listen({ port: 3000 }, (err, address) => {
35+
if (err) {
36+
app.log.error(err);
37+
process.exit(1);
38+
}
39+
app.log.info(`server listening on ${address}`);
40+
});
41+
42+
} catch (err) {
43+
console.log(err);
44+
throw err;
45+
} finally {
46+
process.send("ready");
47+
}
48+
}
49+
50+
run().catch(console.dir);

0 commit comments

Comments
 (0)