Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance improvements for insertMany() #14724

Merged
merged 9 commits into from
Jul 10, 2024
Prev Previous commit
Next Next commit
perf(document): skip parallel validate check when creating new docume…
…nt in insertMany()

Re: #14719
  • Loading branch information
vkarpov15 committed Jul 3, 2024
commit 72cb0b7c7d1599b989929a4a94ea069bcc2393e8
38 changes: 38 additions & 0 deletions benchmarks/insertManySimple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict';

const mongoose = require('../');

run().catch(err => {
console.error(err);
process.exit(-1);
});

async function run() {
await mongoose.connect('mongodb://127.0.0.1:27017/mongoose_benchmark');
const FooSchema = new mongoose.Schema({ foo: String });
const FooModel = mongoose.model('Foo', FooSchema);

if (!process.env.MONGOOSE_BENCHMARK_SKIP_SETUP) {
await FooModel.deleteMany({});
}

const numDocs = 1500;
const docs = [];
for (let i = 0; i < numDocs; ++i) {
docs.push({ foo: 'test foo ' + i });
}

const numIterations = 200;
const insertStart = Date.now();
for (let i = 0; i < numIterations; ++i) {
await FooModel.insertMany(docs);
}
const insertEnd = Date.now();

const results = {
'Average insertMany time ms': +((insertEnd - insertStart) / numIterations).toFixed(2)
};

console.log(JSON.stringify(results, null, ' '));
process.exit(0);
}
23 changes: 12 additions & 11 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -2601,17 +2601,6 @@ Document.prototype.validate = async function validate(pathsToValidate, options)
let parallelValidate;
this.$op = 'validate';

if (this.$isSubdocument != null) {
// Skip parallel validate check for subdocuments
} else if (this.$__.validating) {
parallelValidate = new ParallelValidateError(this, {
parentStack: options && options.parentStack,
conflictStack: this.$__.validating.stack
});
} else {
this.$__.validating = new ParallelValidateError(this, { parentStack: options && options.parentStack });
}

if (arguments.length === 1) {
if (typeof arguments[0] === 'object' && !Array.isArray(arguments[0])) {
options = arguments[0];
Expand All @@ -2622,6 +2611,18 @@ Document.prototype.validate = async function validate(pathsToValidate, options)
const isOnePathOnly = options.pathsToSkip.indexOf(' ') === -1;
options.pathsToSkip = isOnePathOnly ? [options.pathsToSkip] : options.pathsToSkip.split(' ');
}
const _skipParallelValidateCheck = options && options._skipParallelValidateCheck;

if (this.$isSubdocument != null) {
// Skip parallel validate check for subdocuments
} else if (this.$__.validating && !_skipParallelValidateCheck) {
parallelValidate = new ParallelValidateError(this, {
parentStack: options && options.parentStack,
conflictStack: this.$__.validating.stack
});
} else if (!_skipParallelValidateCheck) {
this.$__.validating = new ParallelValidateError(this, { parentStack: options && options.parentStack });
}

if (parallelValidate != null) {
throw parallelValidate;
Expand Down
4 changes: 3 additions & 1 deletion lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -3199,12 +3199,14 @@ Model.$__insertMany = function(arr, options, callback) {
// execute the callback synchronously
return immediate(() => callback(null, doc));
}
let createdNewDoc = false;
if (!(doc instanceof _this)) {
if (doc != null && typeof doc !== 'object') {
return callback(new ObjectParameterError(doc, 'arr.' + index, 'insertMany'));
}
try {
doc = new _this(doc);
createdNewDoc = true;
} catch (err) {
return callback(err);
}
Expand All @@ -3220,7 +3222,7 @@ Model.$__insertMany = function(arr, options, callback) {
// execute the callback synchronously
return immediate(() => callback(null, doc));
}
doc.$validate().then(
doc.$validate(createdNewDoc ? { _skipParallelValidateCheck: true } : null).then(
() => { callback(null, doc); },
error => {
if (ordered === false) {
Expand Down
Loading