From 02a0cf2ab54da6c56a7d7e2a24c4fb39708b21ee Mon Sep 17 00:00:00 2001 From: Valeri Karpov <val@karpov.io> Date: Mon, 27 May 2024 15:26:03 -0400 Subject: [PATCH 1/7] refactor(document): clean up transform option handling --- lib/document.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/document.js b/lib/document.js index 6cce70c486..71511b37a9 100644 --- a/lib/document.js +++ b/lib/document.js @@ -3799,7 +3799,6 @@ Document.prototype.$__handleReject = function handleReject(err) { Document.prototype.$toObject = function(options, json) { const defaultOptions = { - transform: true, flattenDecimals: true }; @@ -3858,6 +3857,7 @@ Document.prototype.$toObject = function(options, json) { _seen: (options && options._seen) || new Map(), _calledWithOptions: options._calledWithOptions }; + delete cloneOptions.transform; const depopulate = options.depopulate || (options._parentOptions && options._parentOptions.depopulate || false); @@ -3882,7 +3882,7 @@ Document.prototype.$toObject = function(options, json) { cloneOptions._skipSingleNestedGetters = false; // remember the root transform function // to save it from being overwritten by sub-transform functions - const originalTransform = options.transform; + //const originalTransform = options.transform; let ret = clone(this._doc, cloneOptions) || {}; @@ -3903,7 +3903,7 @@ Document.prototype.$toObject = function(options, json) { delete ret[this.$__schema.options.versionKey]; } - let transform = options.transform; + let transform = options._calledWithOptions.transform ?? options.transform ?? true; // In the case where a subdocument has its own transform function, we need to // check and see if the parent has a transform (options.transform) and if the @@ -3925,7 +3925,7 @@ Document.prototype.$toObject = function(options, json) { transform = (typeof options.transform === 'function' ? options.transform : opts.transform); } } else { - options.transform = originalTransform; + //options.transform = originalTransform; } if (typeof transform === 'function') { @@ -4146,7 +4146,8 @@ function applyVirtuals(self, json, options, toObjectOptions) { assignPath = path.substring(options.path.length + 1); } if (assignPath.indexOf('.') === -1 && assignPath === path) { - v = clone(self.get(path, { noDottedPath: true }), options); + v = self.get(path, { noDottedPath: true }); + v = clone(v, options); if (v === void 0) { continue; } From 50ce3f384f5bd764aa02b62d9b4167518fda2f3c Mon Sep 17 00:00:00 2001 From: Valeri Karpov <val@karpov.io> Date: Mon, 27 May 2024 16:05:15 -0400 Subject: [PATCH 2/7] perf: avoid creating separate cloneOptions re: #14394 --- lib/document.js | 52 +++++++++++++++++++++---------------------- test/document.test.js | 22 ++++++++++++------ 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/lib/document.js b/lib/document.js index 71511b37a9..0846e0d928 100644 --- a/lib/document.js +++ b/lib/document.js @@ -3847,20 +3847,15 @@ Document.prototype.$toObject = function(options, json) { // `clone()` will recursively call `$toObject()` on embedded docs, so we // need the original options the user passed in, plus `_isNested` and // `_parentOptions` for checking whether we need to depopulate. - const cloneOptions = { - ...options, - _isNested: true, - json: json, - minimize: _minimize, - flattenMaps: flattenMaps, - flattenObjectIds: flattenObjectIds, - _seen: (options && options._seen) || new Map(), - _calledWithOptions: options._calledWithOptions - }; - delete cloneOptions.transform; + const cloneOptions = options; + + options.minimize = _minimize; + options._seen = options._seen || new Map(); - const depopulate = options.depopulate || - (options._parentOptions && options._parentOptions.depopulate || false); + const depopulate = options._calledWithOptions.depopulate + ?? options._parentOptions?.depopulate + ?? defaultOptions.depopulate + ?? false; // _isNested will only be true if this is not the top level document, we // should never depopulate the top-level document if (depopulate && options._isNested && this.$__.wasPopulated) { @@ -3895,7 +3890,14 @@ Document.prototype.$toObject = function(options, json) { } } - if (options.virtuals || (options.getters && options.virtuals !== false)) { + const getters = options._calledWithOptions.getters + ?? defaultOptions.getters + ?? false; + const virtuals = options._calledWithOptions.virtuals + ?? defaultOptions.virtuals + ?? undefined; + + if (virtuals || (getters && virtuals !== false)) { applyVirtuals(this, ret, cloneOptions, options); } @@ -3903,7 +3905,13 @@ Document.prototype.$toObject = function(options, json) { delete ret[this.$__schema.options.versionKey]; } - let transform = options._calledWithOptions.transform ?? options.transform ?? true; + let transform = options._calledWithOptions.transform ?? true; + let transformFunction = undefined; + if (transform === true) { + transformFunction = defaultOptions.transform; + } else if (typeof transform === 'function') { + transformFunction = transform; + } // In the case where a subdocument has its own transform function, we need to // check and see if the parent has a transform (options.transform) and if the @@ -3918,18 +3926,8 @@ Document.prototype.$toObject = function(options, json) { omitDeselectedFields(this, ret); } - if (transform === true || (schemaOptions.toObject && transform)) { - const opts = options.json ? schemaOptions.toJSON : schemaOptions.toObject; - - if (opts) { - transform = (typeof options.transform === 'function' ? options.transform : opts.transform); - } - } else { - //options.transform = originalTransform; - } - - if (typeof transform === 'function') { - const xformed = transform(this, ret, options); + if (typeof transformFunction === 'function') { + const xformed = transformFunction(this, ret, options); if (typeof xformed !== 'undefined') { ret = xformed; } diff --git a/test/document.test.js b/test/document.test.js index 066699766f..e5dcfa3bb1 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -711,11 +711,6 @@ describe('document', function() { name: String, email: String }); - const topicSchema = new Schema({ - title: String, - email: String, - followers: [userSchema] - }); userSchema.options.toObject = { transform: function(doc, ret) { @@ -723,6 +718,12 @@ describe('document', function() { } }; + const topicSchema = new Schema({ + title: String, + email: String, + followers: [userSchema] + }); + topicSchema.options.toObject = { transform: function(doc, ret) { ret.title = ret.title.toLowerCase(); @@ -833,7 +834,10 @@ describe('document', function() { const userSchema = Schema({ firstName: String, company: { - type: { companyId: { type: Schema.Types.ObjectId }, companyName: String } + type: { + companyId: { type: Schema.Types.ObjectId }, + companyName: String + } } }, { toObject: { @@ -849,6 +853,7 @@ describe('document', function() { const User = db.model('User', userSchema); const user = new User({ firstName: 'test', company: { companyName: 'foo' } }); + assert.equal(transformCalls.length, 0); const obj = user.toObject(); assert.strictEqual(obj.company.details, 42); assert.equal(transformCalls.length, 1); @@ -1045,7 +1050,10 @@ describe('document', function() { const userSchema = Schema({ firstName: String, company: { - type: { companyId: { type: Schema.Types.ObjectId }, companyName: String } + type: { + companyId: { type: Schema.Types.ObjectId }, + companyName: String + } } }, { id: false, From 5d185b9ff079beff4aedf45c3e3a6fa53c3bf203 Mon Sep 17 00:00:00 2001 From: Valeri Karpov <val@karpov.io> Date: Thu, 30 May 2024 15:55:05 -0400 Subject: [PATCH 3/7] perf: remove some more unnecessary cloning in $toObject() and correct options to get() Re: #14394 --- lib/document.js | 59 +++++++++++--------------------------- lib/helpers/clone.js | 2 +- test/helpers/clone.test.js | 2 +- 3 files changed, 18 insertions(+), 45 deletions(-) diff --git a/lib/document.js b/lib/document.js index 0846e0d928..bdb6e2e57d 100644 --- a/lib/document.js +++ b/lib/document.js @@ -3798,10 +3798,6 @@ Document.prototype.$__handleReject = function handleReject(err) { */ Document.prototype.$toObject = function(options, json) { - const defaultOptions = { - flattenDecimals: true - }; - const path = json ? 'toJSON' : 'toObject'; const baseOptions = this.constructor && this.constructor.base && @@ -3810,7 +3806,7 @@ Document.prototype.$toObject = function(options, json) { const schemaOptions = this.$__schema && this.$__schema.options || {}; // merge base default options with Schema's set default options if available. // `clone` is necessary here because `utils.options` directly modifies the second input. - Object.assign(defaultOptions, baseOptions, schemaOptions[path]); + const defaultOptions = Object.assign({}, baseOptions, schemaOptions[path]); // If options do not exist or is not an object, set it to empty object options = utils.isPOJO(options) ? { ...options } : {}; @@ -3825,30 +3821,6 @@ Document.prototype.$toObject = function(options, json) { _minimize = schemaOptions.minimize; } - let flattenMaps; - if (options._calledWithOptions.flattenMaps != null) { - flattenMaps = options.flattenMaps; - } else if (defaultOptions.flattenMaps != null) { - flattenMaps = defaultOptions.flattenMaps; - } else { - flattenMaps = schemaOptions.flattenMaps; - } - - let flattenObjectIds; - if (options._calledWithOptions.flattenObjectIds != null) { - flattenObjectIds = options.flattenObjectIds; - } else if (defaultOptions.flattenObjectIds != null) { - flattenObjectIds = defaultOptions.flattenObjectIds; - } else { - flattenObjectIds = schemaOptions.flattenObjectIds; - } - - // The original options that will be passed to `clone()`. Important because - // `clone()` will recursively call `$toObject()` on embedded docs, so we - // need the original options the user passed in, plus `_isNested` and - // `_parentOptions` for checking whether we need to depopulate. - const cloneOptions = options; - options.minimize = _minimize; options._seen = options._seen || new Map(); @@ -3859,7 +3831,7 @@ Document.prototype.$toObject = function(options, json) { // _isNested will only be true if this is not the top level document, we // should never depopulate the top-level document if (depopulate && options._isNested && this.$__.wasPopulated) { - return clone(this.$__.wasPopulated.value || this._id, cloneOptions); + return clone(this.$__.wasPopulated.value || this._id, options); } // merge default options with input options. @@ -3872,40 +3844,41 @@ Document.prototype.$toObject = function(options, json) { options.json = json; options.minimize = _minimize; - cloneOptions._parentOptions = options; + options._parentOptions = options; - cloneOptions._skipSingleNestedGetters = false; + options._skipSingleNestedGetters = false; // remember the root transform function // to save it from being overwritten by sub-transform functions - //const originalTransform = options.transform; + // const originalTransform = options.transform; - let ret = clone(this._doc, cloneOptions) || {}; + let ret = clone(this._doc, options) || {}; - cloneOptions._skipSingleNestedGetters = true; - if (options.getters) { - applyGetters(this, ret, cloneOptions); + options._skipSingleNestedGetters = true; + const getters = options._calledWithOptions.getters + ?? options.getters + ?? defaultOptions.getters + ?? false; + if (getters) { + applyGetters(this, ret, options); if (options.minimize) { ret = minimize(ret) || {}; } } - const getters = options._calledWithOptions.getters - ?? defaultOptions.getters - ?? false; const virtuals = options._calledWithOptions.virtuals ?? defaultOptions.virtuals ?? undefined; if (virtuals || (getters && virtuals !== false)) { - applyVirtuals(this, ret, cloneOptions, options); + applyVirtuals(this, ret, options, options); } if (options.versionKey === false && this.$__schema.options.versionKey) { delete ret[this.$__schema.options.versionKey]; } - let transform = options._calledWithOptions.transform ?? true; + const transform = options._calledWithOptions.transform ?? true; let transformFunction = undefined; if (transform === true) { transformFunction = defaultOptions.transform; @@ -4144,7 +4117,7 @@ function applyVirtuals(self, json, options, toObjectOptions) { assignPath = path.substring(options.path.length + 1); } if (assignPath.indexOf('.') === -1 && assignPath === path) { - v = self.get(path, { noDottedPath: true }); + v = self.get(path, null, { noDottedPath: true }); v = clone(v, options); if (v === void 0) { continue; diff --git a/lib/helpers/clone.js b/lib/helpers/clone.js index a7b5f2f2fe..fafb2f3063 100644 --- a/lib/helpers/clone.js +++ b/lib/helpers/clone.js @@ -40,7 +40,7 @@ function clone(obj, options, isArrayChild) { // Single nested subdocs should apply getters later in `applyGetters()` // when calling `toObject()`. See gh-7442, gh-8295 if (options._skipSingleNestedGetters && obj.$isSingleNested) { - options = Object.assign({}, options, { getters: false }); + options._calledWithOptions = Object.assign({}, options._calledWithOptions || {}, { getters: false }); } if (options.retainDocuments && obj.$__ != null) { const clonedDoc = obj.$clone(); diff --git a/test/helpers/clone.test.js b/test/helpers/clone.test.js index 7d84a5ed03..80540041c2 100644 --- a/test/helpers/clone.test.js +++ b/test/helpers/clone.test.js @@ -88,7 +88,7 @@ describe('clone', () => { $isSingleNested: true, toObject(cloneOpts) { assert.deepStrictEqual( - Object.assign({}, baseOpts, { getters: false }), + Object.assign({}, baseOpts), cloneOpts ); const obj = JSON.parse(JSON.stringify(base)); From 1c7cf1740d9b0c0ddde77f94537732d9e2a9ebf4 Mon Sep 17 00:00:00 2001 From: Valeri Karpov <val@karpov.io> Date: Fri, 31 May 2024 10:18:34 -0400 Subject: [PATCH 4/7] remove old benchmarks, add new benchmark for #14394 --- benchmarks/benchjs/casting.js | 151 --- benchmarks/benchjs/delete.js | 136 --- benchmarks/benchjs/insert.js | 189 --- benchmarks/benchjs/multiop.js | 482 -------- benchmarks/benchjs/population.js | 410 ------- benchmarks/benchjs/read.js | 319 ----- benchmarks/bigboard.json | 1909 ------------------------------ benchmarks/clone.js | 79 -- benchmarks/create.js | 46 - benchmarks/index.js | 151 --- benchmarks/mapOfSubdocs.js | 5 +- benchmarks/mem.js | 165 --- benchmarks/populate.js | 84 -- benchmarks/recursiveToObject.js | 60 + benchmarks/validate.js | 68 -- 15 files changed, 61 insertions(+), 4193 deletions(-) delete mode 100644 benchmarks/benchjs/casting.js delete mode 100644 benchmarks/benchjs/delete.js delete mode 100644 benchmarks/benchjs/insert.js delete mode 100644 benchmarks/benchjs/multiop.js delete mode 100644 benchmarks/benchjs/population.js delete mode 100644 benchmarks/benchjs/read.js delete mode 100644 benchmarks/bigboard.json delete mode 100644 benchmarks/clone.js delete mode 100644 benchmarks/create.js delete mode 100644 benchmarks/index.js delete mode 100644 benchmarks/mem.js delete mode 100644 benchmarks/populate.js create mode 100644 benchmarks/recursiveToObject.js delete mode 100644 benchmarks/validate.js diff --git a/benchmarks/benchjs/casting.js b/benchmarks/benchjs/casting.js deleted file mode 100644 index f7027eed6b..0000000000 --- a/benchmarks/benchjs/casting.js +++ /dev/null @@ -1,151 +0,0 @@ -'use strict'; -const mongoose = require('../../lib'); -const Benchmark = require('benchmark'); - -const suite = new Benchmark.Suite(); - -const Schema = mongoose.Schema; -const ObjectId = Schema.Types.ObjectId; -const utils = require('../../lib/utils.js'); - -// to make things work in the way the are normally described online... -/* - *global.Schema = Schema; - *global.mongoose = mongoose; - */ - -/** - * These are all the benchmark tests for casting stuff - */ - -const Comments = new Schema(); - -Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments], -}); - -const BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number, - }, - published: Boolean, - mixed: {}, - numbers: [Number], - tags: [String], - owners: [ObjectId], - comments: [Comments], - def: { - type: String, - default: 'kandinsky', - }, -}); - -const commentData = { - title: 'test comment', - date: new Date(), - body: 'this be some crazzzyyyyy text that would go in a comment', - comments: [{ title: 'second level', date: new Date(), body: 'texttt' }], -}; - -const blogData = { - title: 'dummy post', - author: 'somebody', - slug: 'test.post', - date: new Date(), - meta: { - date: new Date(), - visitors: 9001, - }, - published: true, - mixed: { - thisIsRandom: true, - }, - numbers: [1, 2, 7, 10, 23432], - tags: ['test', 'BENCH', 'things', 'more things'], - def: 'THANGS!!!', - comments: [], -}; - -const blogData10 = utils.clone(blogData); -const blogData100 = utils.clone(blogData); -const blogData1000 = utils.clone(blogData); -const blogData10000 = utils.clone(blogData); - -for (let i = 0; i < 10; i++) { - blogData10.comments.push(commentData); -} -for (let i = 0; i < 100; i++) { - blogData100.comments.push(commentData); -} -for (let i = 0; i < 1000; i++) { - blogData1000.comments.push(commentData); -} -for (let i = 0; i < 10000; i++) { - blogData10000.comments.push(commentData); -} - -mongoose.model('BlogPost', BlogPost); - -suite - .add('Casting - Embedded Docs - 0 Docs', { - fn: function () { - const BlogPost = mongoose.model('BlogPost'); - const bp = new BlogPost(); - bp.init(blogData); - }, - }) - .add('Casting - Embedded Docs - 10 Docs', { - fn: function () { - const BlogPost = mongoose.model('BlogPost'); - const bp = new BlogPost(); - bp.init(blogData10); - }, - }) - .add('Casting - Embedded Docs - 100 Docs', { - fn: function () { - const BlogPost = mongoose.model('BlogPost'); - const bp = new BlogPost(); - bp.init(blogData100); - }, - }) - .add('Casting - Embedded Docs - 1000 Docs', { - fn: function () { - const BlogPost = mongoose.model('BlogPost'); - const bp = new BlogPost(); - bp.init(blogData1000); - }, - }) - .add('Casting - Embedded Docs - 10000 Docs', { - fn: function () { - const BlogPost = mongoose.model('BlogPost'); - const bp = new BlogPost(); - bp.init(blogData10000); - }, - }) - .on('cycle', function (evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .on('complete', function () { - if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) { - const outObj = {}; - this.forEach(function (item) { - const out = {}; - out.stats = item.stats; - delete out.stats.sample; - out.ops = item.hz; - outObj[item.name.replace(/\s/g, '')] = out; - }); - console.dir(outObj, { depth: null, colors: true }); - } - }) - .run({ async: true }); diff --git a/benchmarks/benchjs/delete.js b/benchmarks/benchjs/delete.js deleted file mode 100644 index 1d717f7f6e..0000000000 --- a/benchmarks/benchjs/delete.js +++ /dev/null @@ -1,136 +0,0 @@ -'use strict'; -const mongoose = require('../../lib'); -const Benchmark = require('benchmark'); - -const suite = new Benchmark.Suite(); - -const Schema = mongoose.Schema; -const mongoClient = require('mongodb').MongoClient; - -// to make things work in the way the are normally described online... -/* - *global.Schema = Schema; - *global.mongoose = mongoose; - */ - -/** - * These are all the benchmark tests for deleting data - */ - -mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { - if (err) { - throw err; - } - mongoClient.connect('mongodb://127.0.0.1', function (err, client) { - if (err) { - throw err; - } - - const db = client.db('mongoose-bench'); - - const UserSchema = new Schema({ - name: String, - age: Number, - likes: [String], - address: String, - }); - - const User = mongoose.model('User', UserSchema); - const user = db.collection('user'); - - const mIds = []; - const dIds = []; - - const data = { - name: 'name', - age: 0, - likes: ['dogs', 'cats', 'pizza'], - address: ' Nowhere-ville USA', - }; - - // insert all of the data here - let count = 1000; - for (let i = 0; i < 500; i++) { - User.create(data, function (err, u) { - if (err) { - throw err; - } - mIds.push(u.id); - --count || next(); - }); - const nData = {}; - nData.name = data.name; - nData.age = data.age; - nData.likes = data.likes; - nData.address = data.address; - user.insertOne(nData, function (err, res) { - dIds.push(res.insertedId); - --count || next(); - }); - } - - function closeDB() { - User.count(function (err, res) { - if (res !== 0) { - console.log('Still mongoose entries left...'); - } - mongoose.disconnect(); - }); - user.count({}, function (err, res) { - if (res !== 0) { - console.log('Still driver entries left...'); - } - if (err) { - throw err; - } - client.close(); - }); - } - - suite - .add('Delete - Mongoose', { - defer: true, - fn: function (deferred) { - User.remove({ _id: mIds.pop() }, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Delete - Driver', { - defer: true, - fn: function (deferred) { - user.deleteOne({ _id: dIds.pop() }, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .on('cycle', function (evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .on('complete', function () { - closeDB(); - if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) { - const outObj = {}; - this.forEach(function (item) { - const out = {}; - out.stats = item.stats; - delete out.stats.sample; - out.ops = item.hz; - outObj[item.name.replace(/\s/g, '')] = out; - }); - console.dir(outObj, { depth: null, colors: true }); - } - }); - function next() { - suite.run({ async: true }); - } - }); -}); diff --git a/benchmarks/benchjs/insert.js b/benchmarks/benchjs/insert.js deleted file mode 100644 index cd01bfb606..0000000000 --- a/benchmarks/benchjs/insert.js +++ /dev/null @@ -1,189 +0,0 @@ -'use strict'; -const mongoose = require('../../lib'); -const Benchmark = require('benchmark'); - -const suite = new Benchmark.Suite(); - -const Schema = mongoose.Schema; -const mongoClient = require('mongodb').MongoClient; -const utils = require('../../lib/utils.js'); -const ObjectId = Schema.Types.ObjectId; - -// to make things work in the way the are normally described online... -/* - *global.Schema = Schema; - *global.mongoose = mongoose; - */ - -/** - * These are all the benchmark tests for inserting data - */ - -mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { - if (err) { - throw err; - } - mongoClient.connect( - 'mongodb://127.0.0.1/mongoose-bench', - function (err, client) { - if (err) { - throw err; - } - - const db = client.db('mongoose-bench'); - - const Comments = new Schema(); - Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments], - }); - - let BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number, - }, - published: Boolean, - mixed: {}, - numbers: [Number], - tags: [String], - owners: [ObjectId], - comments: [Comments], - def: { - type: String, - default: 'kandinsky', - }, - }); - - const blogData = { - title: 'dummy post', - author: 'somebody', - slug: 'test.post', - date: new Date(), - meta: { date: new Date(), visitors: 9001 }, - published: true, - mixed: { thisIsRandom: true }, - numbers: [1, 2, 7, 10, 23432], - tags: ['test', 'BENCH', 'things', 'more things'], - def: 'THANGS!!!', - comments: [], - }; - const commentData = { - title: 'test comment', - date: new Date(), - body: 'this be some crazzzyyyyy text that would go in a comment', - comments: [ - { - title: 'second level', - date: new Date(), - body: 'texttt', - }, - ], - }; - for (let i = 0; i < 5; i++) { - blogData.comments.push(commentData); - } - const data = { - name: 'name', - age: 0, - likes: ['dogs', 'cats', 'pizza'], - address: ' Nowhere-ville USA', - }; - - const UserSchema = new Schema({ - name: String, - age: Number, - likes: [String], - address: String, - }); - - const User = mongoose.model('User', UserSchema); - BlogPost = mongoose.model('BlogPost', BlogPost); - const user = db.collection('user'); - const blogpost = db.collection('blogpost'); - - function closeDB() { - mongoose.connection.db.dropDatabase(function () { - mongoose.disconnect(); - process.exit(); - }); - } - - suite - .add('Insert - Mongoose - Basic', { - defer: true, - fn: function (deferred) { - const nData = utils.clone(data); - User.create(nData, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Insert - Driver - Basic', { - defer: true, - fn: function (deferred) { - const nData = utils.clone(data); - user.insertOne(nData, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Insert - Mongoose - Embedded Docs', { - defer: true, - fn: function (deferred) { - const bp = utils.clone(blogData); - BlogPost.create(bp, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Insert - Driver - Embedded Docs', { - defer: true, - fn: function (deferred) { - const bp = utils.clone(blogData); - blogpost.insertOne(bp, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .on('cycle', function (evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .on('complete', function () { - closeDB(); - if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) { - const outObj = {}; - this.forEach(function (item) { - const out = {}; - out.stats = item.stats; - delete out.stats.sample; - out.ops = item.hz; - outObj[item.name.replace(/\s/g, '')] = out; - }); - console.dir(outObj, { depth: null, colors: true }); - } - }) - .run({ async: true }); - } - ); -}); diff --git a/benchmarks/benchjs/multiop.js b/benchmarks/benchjs/multiop.js deleted file mode 100644 index c3f73d1f73..0000000000 --- a/benchmarks/benchjs/multiop.js +++ /dev/null @@ -1,482 +0,0 @@ -'use strict'; -const mongoose = require('../../lib'); -const Benchmark = require('benchmark'); - -const suite = new Benchmark.Suite(); - -const Schema = mongoose.Schema; -const ObjectId = Schema.Types.ObjectId; -const mongoClient = require('mongodb').MongoClient; -const utils = require('../../lib/utils.js'); - -// to make things work in the way the are normally described online... -/* - *global.Schema = Schema; - *global.mongoose = mongoose; - */ - -/** - * These are all the benchmark tests for mixed data operations - */ - -mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { - if (err) { - throw err; - } - mongoClient.connect('mongodb://127.0.0.1', function (err, client) { - if (err) { - throw err; - } - - const db = client.db('mongoose-bench'); - - const Comments = new Schema(); - Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments], - }); - - let BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number, - }, - published: Boolean, - mixed: {}, - numbers: [Number], - tags: [String], - owners: [ObjectId], - comments: [Comments], - def: { type: String, default: 'kandinsky' }, - }); - - const blogData = { - title: 'dummy post', - author: 'somebody', - slug: 'test.post', - date: new Date(), - meta: { - date: new Date(), - visitors: 9001, - }, - published: true, - mixed: { - thisIsRandom: true, - }, - numbers: [1, 2, 7, 10, 23432], - tags: ['test', 'BENCH', 'things', 'more things'], - def: 'THANGS!!!', - comments: [], - }; - const commentData = { - title: 'test comment', - date: new Date(), - body: 'this be some crazzzyyyyy text that would go in a comment', - comments: [ - { - title: 'second level', - date: new Date(), - body: 'texttt', - }, - ], - }; - for (let i = 0; i < 5; i++) { - blogData.comments.push(commentData); - } - const UserSchema = new Schema({ - name: String, - age: Number, - likes: [String], - address: String, - }); - - const User = mongoose.model('User', UserSchema); - BlogPost = mongoose.model('BlogPost', BlogPost); - const user = db.collection('user'); - const blogpost = db.collection('blogpost'); - - const mIds = []; - const dIds = []; - - const bmIds = []; - const bdIds = []; - - const data = { - name: 'name', - age: 0, - likes: ['dogs', 'cats', 'pizza'], - address: ' Nowhere-ville USA', - }; - - // insert all of the data here - let count = 4000; - for (let i = 0; i < 1000; i++) { - data.age = Math.floor(Math.random() * 50); - User.create(data, function (err, u) { - if (err) { - throw err; - } - mIds.push(u.id); - --count || next(); - }); - const nData = utils.clone(data); - user.insertOne(nData, function (err, res) { - if (err) { - throw err; - } - dIds.push(res.insertedIds); - --count || next(); - }); - BlogPost.create(blogData, function (err, bp) { - if (err) { - throw err; - } - bmIds.push(bp.id); - --count || next(); - }); - - const bpData = utils.clone(blogData); - blogpost.insertOne(bpData, function (err, res) { - if (err) { - throw err; - } - bdIds.push(res.insertedId); - --count || next(); - }); - } - - let mi = 0, - di = 0, - bmi = 0, - bdi = 0; - - function getNextmId() { - mi = ++mi % mIds.length; - return mIds[mi]; - } - - function getNextdId() { - di = ++di % dIds.length; - return dIds[di]; - } - - function getNextbmId() { - bmi = ++bmi % bmIds.length; - return bmIds[bmi]; - } - - function getNextbdId() { - bdi = ++bdi % bdIds.length; - return bdIds[bdi]; - } - - function closeDB() { - mongoose.connection.db.dropDatabase(function () { - mongoose.disconnect(); - process.exit(); - }); - } - - suite - .add('Multi-Op - Mongoose - Heavy Read, low write', { - defer: true, - fn: function (deferred) { - let count = 150; - for (let i = 0; i < 150; i++) { - User.findOne({ _id: getNextmId() }, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - if (i % 15 === 0) { - const nData = utils.clone(data); - User.create(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Driver - Heavy Read, low write', { - defer: true, - fn: function (deferred) { - let count = 150; - for (let i = 0; i < 150; i++) { - user.findOne({ _id: getNextdId() }, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - if (i % 15 === 0) { - const nData = utils.clone(data); - user.insertOne(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Mongoose - Embedded Docs - Heavy Read, low write', { - defer: true, - fn: function (deferred) { - let count = 150; - for (let i = 0; i < 150; i++) { - BlogPost.findOne({ _id: getNextbmId() }, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - if (i % 15 === 0) { - const nData = utils.clone(blogData); - BlogPost.create(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Driver - Embedded Docs - Heavy Read, low write', { - defer: true, - fn: function (deferred) { - let count = 150; - for (let i = 0; i < 150; i++) { - blogpost.findOne({ _id: getNextbdId() }, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - if (i % 15 === 0) { - const nData = utils.clone(blogData); - blogpost.insertOne(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Mongoose - Heavy Write, low read', { - defer: true, - fn: function (deferred) { - let count = 150; - - for (let i = 0; i < 150; i++) { - const nData = utils.clone(data); - User.create(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - if (i % 15 === 0) { - User.findOne({ _id: getNextmId() }, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Driver - Heavy Write, low read', { - defer: true, - fn: function (deferred) { - let count = 150; - - for (let i = 0; i < 150; i++) { - const nData = utils.clone(data); - user.insertOne(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - if (i % 15 === 0) { - user.findOne({ _id: getNextdId() }, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Mongoose - Embedded Docs - Heavy Write, low read', { - defer: true, - fn: function (deferred) { - let count = 150; - - for (let i = 0; i < 150; i++) { - const nData = utils.clone(blogData); - BlogPost.create(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - if (i % 15 === 0) { - BlogPost.findOne({ _id: getNextbmId() }, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Driver - Embedded Docs - Heavy Write, low read', { - defer: true, - fn: function (deferred) { - let count = 150; - - for (let i = 0; i < 150; i++) { - const nData = utils.clone(blogData); - blogpost.insertOne(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - if (i % 15 === 0) { - blogpost.findOne({ _id: getNextbdId() }, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Mongoose - Embedded Docs - Read-write-update', { - defer: true, - fn: function (deferred) { - let count = 150; - let updates = 0; - for (let i = 0; i < 150; i++) { - BlogPost.findOne({ _id: getNextbmId() }, function (err, res) { - if (err) { - throw err; - } - if (updates < 20) { - updates++; - res.author = 'soemthing new'; - res.comments.push(commentData); - res.title = 'something newerrrr'; - res.save(function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } else { - --count || deferred.resolve(); - } - }); - if (i % 15 === 0) { - const nData = utils.clone(blogData); - BlogPost.create(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .add('Multi-Op - Driver - Embedded Docs - Read-write-update', { - defer: true, - fn: function (deferred) { - let count = 150; - let updates = 0; - for (let i = 0; i < 150; i++) { - blogpost.findOne({ _id: getNextbdId() }, function (err, bp) { - if (err) { - throw err; - } - if (updates < 20) { - updates++; - blogpost.updateOne( - { _id: bp._id }, - { - $set: { - author: 'something new', - title: 'something newerrrr', - }, - $push: { - comments: commentData, - }, - }, - { upsert: true }, - function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - } - ); - } else { - --count || deferred.resolve(); - } - }); - if (i % 15 === 0) { - const nData = utils.clone(blogData); - blogpost.insertOne(nData, function (err) { - if (err) { - throw err; - } - --count || deferred.resolve(); - }); - } - } - }, - }) - .on('cycle', function (evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .on('complete', function () { - closeDB(); - if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) { - const outObj = {}; - this.forEach(function (item) { - const out = {}; - out.stats = item.stats; - delete out.stats.sample; - out.ops = item.hz; - outObj[item.name.replace(/\s/g, '')] = out; - }); - console.dir(outObj, { depth: null, colors: true }); - } - }); - function next() { - suite.run({ async: true }); - } - }); -}); diff --git a/benchmarks/benchjs/population.js b/benchmarks/benchjs/population.js deleted file mode 100644 index dc55ac1cae..0000000000 --- a/benchmarks/benchjs/population.js +++ /dev/null @@ -1,410 +0,0 @@ -'use strict'; -const mongoose = require('../../lib'); -const Benchmark = require('benchmark'); - -const suite = new Benchmark.Suite(); - -const Schema = mongoose.Schema; -const ObjectId = Schema.Types.ObjectId; -const utils = require('../../lib/utils.js'); - -// to make things work in the way the are normally described online... -/* - *global.Schema = Schema; - *global.mongoose = mongoose; - */ - -/** - * These are all the benchmark tests for population ops - */ - -mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { - if (err) { - throw err; - } - - const commentSchema = new Schema(); - commentSchema.add({ - title: String, - date: Date, - body: String, - }); - const dummy1Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - const dummy2Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - const dummy3Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - const dummy4Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - const dummy5Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - const dummy6Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - const dummy7Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - const dummy8Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - const dummy9Schema = new Schema({ - title: String, - isThisTest: Boolean, - }); - - let BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number, - }, - published: Boolean, - mixed: {}, - numbers: [Number], - tags: [String], - owners: [ObjectId], - comments: [{ type: ObjectId, ref: 'Comment' }], - dummy1: [{ type: ObjectId, ref: 'Dummy1' }], - dummy2: [{ type: ObjectId, ref: 'Dummy2' }], - dummy3: [{ type: ObjectId, ref: 'Dummy3' }], - dummy4: [{ type: ObjectId, ref: 'Dummy4' }], - dummy5: [{ type: ObjectId, ref: 'Dummy5' }], - dummy6: [{ type: ObjectId, ref: 'Dummy6' }], - dummy7: [{ type: ObjectId, ref: 'Dummy7' }], - dummy8: [{ type: ObjectId, ref: 'Dummy8' }], - dummy9: [{ type: ObjectId, ref: 'Dummy9' }], - def: { type: String, default: 'kandinsky' }, - }); - - const blogData = { - title: 'dummy post', - author: 'somebody', - slug: 'test.post', - date: new Date(), - meta: { date: new Date(), visitors: 9001 }, - published: true, - mixed: { thisIsRandom: true }, - numbers: [1, 2, 7, 10, 23432], - tags: ['test', 'BENCH', 'things', 'more things'], - def: 'THANGS!!!', - comments: [], - dummy1: [], - dummy2: [], - dummy3: [], - dummy4: [], - dummy5: [], - dummy6: [], - dummy7: [], - dummy8: [], - dummy9: [], - }; - const commentData = { - title: 'test comment', - date: new Date(), - body: 'this be some crazzzyyyyy text that would go in a comment', - }; - const dummyData = { - title: 'dummy data~', - isThisTest: true, - }; - const Comments = mongoose.model('Comment', commentSchema); - BlogPost = mongoose.model('BlogPost', BlogPost); - const Dummy1 = mongoose.model('Dummy1', dummy1Schema); - const Dummy2 = mongoose.model('Dummy2', dummy2Schema); - const Dummy3 = mongoose.model('Dummy3', dummy3Schema); - const Dummy4 = mongoose.model('Dummy4', dummy4Schema); - const Dummy5 = mongoose.model('Dummy5', dummy5Schema); - const Dummy6 = mongoose.model('Dummy6', dummy6Schema); - const Dummy7 = mongoose.model('Dummy7', dummy7Schema); - const Dummy8 = mongoose.model('Dummy8', dummy8Schema); - const Dummy9 = mongoose.model('Dummy9', dummy9Schema); - const cIds = []; - const dIds = []; - for (let i = 0; i < 9; i++) { - dIds.push([]); - } - - let cn = 5000; - for (let i = 0; i < 500; i++) { - Comments.create(commentData, function (err, com) { - cIds.push(com.id); - --cn || cont(); - }); - Dummy1.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[0].push(d.id); - --cn || cont(); - }); - Dummy2.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[1].push(d.id); - --cn || cont(); - }); - Dummy3.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[2].push(d.id); - --cn || cont(); - }); - Dummy4.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[3].push(d.id); - --cn || cont(); - }); - Dummy5.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[4].push(d.id); - --cn || cont(); - }); - Dummy6.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[5].push(d.id); - --cn || cont(); - }); - Dummy7.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[6].push(d.id); - --cn || cont(); - }); - Dummy8.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[7].push(d.id); - --cn || cont(); - }); - Dummy9.create(dummyData, function (err, d) { - if (err) { - throw err; - } - dIds[8].push(d.id); - --cn || cont(); - }); - } - - const blog = []; - - function cont() { - blog[0] = utils.clone(blogData); - blog[1] = utils.clone(blogData); - blog[2] = utils.clone(blogData); - blog[3] = utils.clone(blogData); - blogData.comments.push(getNextcId()); - blog[4] = blogData; - - blog[5] = utils.clone(blogData); - blog[6] = utils.clone(blogData); - - for (let i = 0; i < 10; i++) { - blog[0].comments.push(getNextcId()); - } - for (let i = 0; i < 100; i++) { - blog[1].comments.push(getNextcId()); - } - for (let i = 0; i < 1000; i++) { - blog[2].comments.push(getNextcId()); - } - for (let i = 0; i < 10000; i++) { - blog[3].comments.push(getNextcId()); - } - for (let i = 0; i < 100; i++) { - blog[5].comments.push(getNextcId()); - blog[6].comments.push(getNextcId()); - - blog[5].dummy1.push(getNextdId(0)); - blog[5].dummy2.push(getNextdId(1)); - blog[5].dummy3.push(getNextdId(2)); - blog[5].dummy4.push(getNextdId(3)); - - blog[6].dummy1.push(getNextdId(0)); - blog[6].dummy2.push(getNextdId(1)); - blog[6].dummy3.push(getNextdId(2)); - blog[6].dummy4.push(getNextdId(3)); - blog[6].dummy5.push(getNextdId(4)); - blog[6].dummy1.push(getNextdId(5)); - blog[6].dummy2.push(getNextdId(6)); - blog[6].dummy3.push(getNextdId(7)); - blog[6].dummy4.push(getNextdId(8)); - } - - let count = 7; - - function iter(c) { - BlogPost.create(blog[c], function (err, bl) { - if (err) { - throw err; - } - blog[c] = bl; - --count || next(); - }); - } - - // insert all of the data here - for (let i = 0; i < blog.length; i++) { - // use some closure magic to make sure we retain the index - iter(i); - } - } - - let ci = 0; - const di = []; - for (let i = 0; i < 9; i++) { - di.push(0); - } - - function getNextcId() { - ci = ++ci % cIds.length; - return cIds[ci]; - } - - function getNextdId(i) { - di[i] = ++di[i] % dIds[i].length; - return dIds[i][di[i]]; - } - - function closeDB() { - // just a bit simpler... - mongoose.connection.db.dropDatabase(function () { - mongoose.disconnect(); - process.exit(); - }); - } - - suite - .add('Populate - 1 value', { - defer: true, - fn: function (deferred) { - blog[4].populate('comments', function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Populate - 10 values', { - defer: true, - fn: function (deferred) { - blog[0].populate('comments', function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Populate - 100 values', { - defer: true, - fn: function (deferred) { - blog[1].populate('comments', function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Populate - 1000 values', { - defer: true, - fn: function (deferred) { - blog[2].populate('comments', function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Populate - 10000 values', { - defer: true, - fn: function (deferred) { - blog[3].populate('comments', function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Populate - 5 properties', { - defer: true, - fn: function (deferred) { - blog[5].populate( - 'comments dummy1 dummy2 dummy3 dummy4', - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }, - }) - .add('Populate - 10 properties', { - defer: true, - fn: function (deferred) { - blog[6].populate( - 'comments dummy1 dummy2 dummy3 dummy4 dummy5 dummy6 dummy7 dummy8 dummy9', - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }, - }) - - .on('cycle', function (evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .on('complete', function () { - closeDB(); - if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) { - const outObj = {}; - this.forEach(function (item) { - const out = {}; - out.stats = item.stats; - delete out.stats.sample; - out.ops = item.hz; - outObj[item.name.replace(/\s/g, '')] = out; - }); - console.dir(outObj, { depth: null, colors: true }); - } - }); - function next() { - suite.run({ async: true }); - } -}); diff --git a/benchmarks/benchjs/read.js b/benchmarks/benchjs/read.js deleted file mode 100644 index 35d39b9091..0000000000 --- a/benchmarks/benchjs/read.js +++ /dev/null @@ -1,319 +0,0 @@ -'use strict'; - -const mongoose = require('../../lib'); -const Benchmark = require('benchmark'); - -const suite = new Benchmark.Suite(); - -const Schema = mongoose.Schema; -const ObjectId = Schema.Types.ObjectId; -const mongoClient = require('mongodb').MongoClient; -const utils = require('../../lib/utils.js'); - -// to make things work in the way the are normally described online... -/* - *global.Schema = Schema; - *global.mongoose = mongoose; - */ - -/** - * These are all the benchmark tests for reading data - */ - -mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function (err) { - if (err) { - throw err; - } - mongoClient.connect('mongodb://127.0.0.1', function (err, client) { - if (err) { - throw err; - } - - const db = client.db('mongoose-bench'); - - const Comments = new Schema(); - Comments.add({ - title: String, - date: Date, - body: String, - comments: [Comments], - }); - - let BlogPost = new Schema({ - title: String, - author: String, - slug: String, - date: Date, - meta: { - date: Date, - visitors: Number, - }, - published: Boolean, - mixed: {}, - numbers: [Number], - tags: [String], - owners: [ObjectId], - comments: [Comments], - def: { - type: String, - default: 'kandinsky', - }, - }); - - const blogData = { - title: 'dummy post', - author: 'somebody', - slug: 'test.post', - date: new Date(), - meta: { date: new Date(), visitors: 9001 }, - published: true, - mixed: { thisIsRandom: true }, - numbers: [1, 2, 7, 10, 23432], - tags: ['test', 'BENCH', 'things', 'more things'], - def: 'THANGS!!!', - comments: [], - }; - const commentData = { - title: 'test comment', - date: new Date(), - body: 'this be some crazzzyyyyy text that would go in a comment', - comments: [{ title: 'second level', date: new Date(), body: 'texttt' }], - }; - for (let i = 0; i < 5; i++) { - blogData.comments.push(commentData); - } - const UserSchema = new Schema({ - name: String, - age: Number, - likes: [String], - address: String, - }); - - const User = mongoose.model('User', UserSchema); - BlogPost = mongoose.model('BlogPost', BlogPost); - const user = db.collection('user'); - const blogpost = db.collection('blogpost'); - - const mIds = []; - const dIds = []; - - const bmIds = []; - const bdIds = []; - - const data = { - name: 'name', - age: 0, - likes: ['dogs', 'cats', 'pizza'], - address: ' Nowhere-ville USA', - }; - - // insert all of the data here - let count = 4000; - for (let i = 0; i < 1000; i++) { - data.age = Math.floor(Math.random() * 50); - User.create(data, function (err, u) { - if (err) { - throw err; - } - mIds.push(u.id); - --count || next(); - }); - const nData = utils.clone(data); - user.insertOne(nData, function (err, res) { - if (err) { - throw err; - } - dIds.push(res.insertedId); - --count || next(); - }); - BlogPost.create(blogData, function (err, bp) { - if (err) { - throw err; - } - bmIds.push(bp.id); - --count || next(); - }); - - const bpData = utils.clone(blogData); - blogpost.insertOne(bpData, function (err, res) { - if (err) { - throw err; - } - bdIds.push(res.insertedId); - --count || next(); - }); - } - - let mi = 0, - di = 0, - bmi = 0, - bdi = 0; - - function getNextmId() { - mi = ++mi % mIds.length; - return mIds[mi]; - } - - function getNextdId() { - di = ++di % dIds.length; - return dIds[di]; - } - - function getNextbmId() { - bmi = ++bmi % bmIds.length; - return bmIds[bmi]; - } - - function getNextbdId() { - bdi = ++bdi % bdIds.length; - return bdIds[bdi]; - } - - function closeDB() { - mongoose.connection.db.dropDatabase(function () { - mongoose.disconnect(); - process.exit(); - }); - } - - suite - .add('Read - Mongoose - Basic', { - defer: true, - fn: function (deferred) { - User.findOne({ _id: getNextmId() }, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Read - Driver - Basic', { - defer: true, - fn: function (deferred) { - user.findOne({ _id: getNextdId() }, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Read - Mongoose - With lean', { - defer: true, - fn: function (deferred) { - User.findOne( - { _id: getNextmId() }, - {}, - { lean: true }, - function (err) { - if (err) { - throw err; - } - deferred.resolve(); - } - ); - }, - }) - .add('Read - Mongoose - Multiple Items', { - defer: true, - fn: function (deferred) { - const ids = []; - for (let i = 0; i < 25; i++) { - ids.push(getNextmId()); - } - User.find({ _id: { $in: ids } }, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Read - Driver - Multiple Items', { - defer: true, - fn: function (deferred) { - const ids = []; - for (let i = 0; i < 25; i++) { - ids.push(getNextdId()); - } - user.find({ _id: { $in: ids } }).toArray(function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Read - Mongoose - Non-index', { - defer: true, - fn: function (deferred) { - const age = Math.floor(Math.random() * 50); - - User.find({ age: age }, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Read - Driver - Non-index', { - defer: true, - fn: function (deferred) { - const age = Math.floor(Math.random() * 50); - - user.find({ age: age }).toArray(function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Read - Mongoose - Embedded Docs', { - defer: true, - fn: function (deferred) { - BlogPost.find({ _id: getNextbmId() }, function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .add('Read - Driver - Embedded Docs', { - defer: true, - fn: function (deferred) { - blogpost.find({ _id: getNextbdId() }).toArray(function (err) { - if (err) { - throw err; - } - deferred.resolve(); - }); - }, - }) - .on('cycle', function (evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .on('complete', function () { - closeDB(); - if (!process.env.MONGOOSE_DEV && !process.env.PULL_REQUEST) { - const outObj = {}; - this.forEach(function (item) { - const out = {}; - out.stats = item.stats; - delete out.stats.sample; - out.ops = item.hz; - outObj[item.name.replace(/\s/g, '')] = out; - }); - console.dir(outObj, { depth: null, colors: true }); - } - }); - function next() { - suite.run({ async: true }); - } - }); -}); diff --git a/benchmarks/bigboard.json b/benchmarks/bigboard.json deleted file mode 100644 index 0c22211c9f..0000000000 --- a/benchmarks/bigboard.json +++ /dev/null @@ -1,1909 +0,0 @@ -{ - "_id": "4d5ea62fd76aa1136000000c", - "checklists": [{ - "_id": "4daee890aae47fe55305dd72", - "checkItems": [{ - "_id": "4daee8a2aae47fe55305eabf", - "pos": 32768, - "type": "check", - "name": "delete checklists" - }, { - "_id": "4daee8a6aae47fe55305eb4e", - "pos": 49152, - "type": "check", - "name": "delete checklist items" - }, { - "_id": "4daeec4caae47fe5530730be", - "pos": 65536, - "type": "check", - "name": "Link to card on action in activity feed" - }, { - "_id": "4daeeca6aae47fe5530748b8", - "pos": 81920, - "type": "check", - "name": "Edit controls on new task input" - }, { - "_id": "4daeeda4aae47fe553080e92", - "pos": 98304, - "type": "check", - "name": "Actions for checklist item add, change, delete, reorder, etc." - }, { - "_id": "4db06f77c9fd63357d0a44ed", - "pos": 114688, - "type": "check", - "name": "Click 'Add checklist' -> focus on new task, let title be 'Checklist', but editable" - }], - "name": "Features" - }, { - "checkItems": [{ - "_id": "4db09065c9fd63357d118d0f", - "pos": 0, - "type": "check", - "name": "Make it obvious that you can't do stuff to the board" - }, { - "_id": "4db0906fc9fd63357d118d75", - "pos": 16384, - "type": "check", - "name": "/#browse/" - }, { - "_id": "4db0908ac9fd63357d118e54", - "pos": 32768, - "type": "check", - "name": "Cut you off from further updates when you can't see the board any more" - }], - "_id": "4db09054c9fd63357d117284", - "name": "Remaining" - }, { - "checkItems": [{ - "_id": "4db5b8a9697ba7cc023bc737", - "pos": 0, - "type": "check", - "name": "You can check things off of a checklist [brett]" - }, { - "_id": "4db5b8bf697ba7cc023bc874", - "pos": 16384, - "type": "check", - "name": "Moving lists [brett]" - }, { - "_id": "4db5b8fa697ba7cc023be27f", - "pos": 32768, - "type": "check", - "name": "Assign members by dragging" - }, { - "_id": "4db5b8fc697ba7cc023be2bb", - "pos": 49152, - "type": "check", - "name": "Removing members from cards via avatar pop over menu" - }, { - "_id": "4db5b909697ba7cc023be3b7", - "pos": 65536, - "type": "check", - "name": "Remove members from board via sidebar" - }, { - "_id": "4db5b90e697ba7cc023be406", - "pos": 81920, - "type": "check", - "name": "Close lists via list menu" - }, { - "_id": "4db5bae6697ba7cc023dea6a", - "pos": 98304, - "type": "check", - "name": "Do everything via board menu" - }, { - "_id": "4db5cef7697ba7cc023f97f4", - "pos": 114688, - "type": "check", - "name": "we lost list reopen" - }], - "_id": "4db43519697ba7cc0227e6d7", - "name": "Places where it still looks like you can edit" - }, { - "checkItems": [{ - "_id": "4db747935413f9d20c0b5eaa", - "pos": 0, - "type": "check", - "name": "Finish checklists v2" - }, { - "_id": "4db7479b5413f9d20c0b5eeb", - "pos": 16384, - "type": "check", - "name": "Delete this checklist" - }], - "_id": "4db745f75413f9d20c0adb0d", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4db8384582ab23241000c157", - "pos": 0, - "type": "check", - "name": "Links in comments causing dialog window width problems" - }, { - "_id": "4db8386782ab23241000cb40", - "pos": 16384, - "type": "check", - "name": "'card operations' (grey dude, close) showing up on click" - }, { - "_id": "4db8388882ab23241000d0ab", - "pos": 32768, - "type": "check", - "name": "scrolltop not being set correctly" - }], - "_id": "4db8383582ab232410009fc4", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4db852b24b06719a1005014c", - "pos": 0, - "type": "check", - "name": "Cursor is pointer for list and board titles on public board" - }, { - "_id": "4db861334b06719a10076026", - "pos": 16384, - "type": "check", - "name": "Looks like I can add checklist items to cards that already hace checklists" - }, { - "_id": "4db8615f4b06719a10077a73", - "pos": 32768, - "type": "check", - "name": "Looks like I can edit checklist titles" - }], - "_id": "4db852a54b06719a1004f9b9", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dbafb7c6cc6af2018042d9d", - "pos": 16384, - "type": "check", - "name": "Link 'Boards' to member/boards from the member page" - }, { - "_id": "4dbafb836cc6af2018042e0c", - "pos": 32768, - "type": "check", - "name": "Link to 'Boards' from the menu" - }, { - "_id": "4dbafb8f6cc6af2018042ee8", - "pos": 49152, - "type": "check", - "name": "Remove the boards from the member detail page" - }, { - "_id": "4dbafbad6cc6af2018045d3c", - "pos": 65536, - "type": "check", - "name": "Make server-side data provider data/board/list/mine/updates" - }, { - "_id": "4dbafc706cc6af2018049bd2", - "pos": 98304, - "type": "check", - "name": "BoardStatsListView" - }, { - "_id": "4dbafc766cc6af2018049c3f", - "pos": 114688, - "type": "check", - "name": "MemberBoardsView" - }, { - "_id": "4dbee92360f4e2b21d01a2ed", - "pos": 131072, - "type": "check", - "name": "Merge views and templates for profile and board pages" - }], - "_id": "4dbafb686cc6af20180422b0", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dc7e84ee92755263100e7d1", - "pos": 16384, - "type": "check", - "name": "actions.js [brett]" - }, { - "_id": "4dc7e858e92755263100e87b", - "pos": 32768, - "type": "check", - "name": "notifications.js [brett]" - }], - "_id": "4dc7e841e92755263100e045", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dc7e8dfe927552631012742", - "pos": 16384, - "type": "check", - "name": "Patch controller" - }, { - "_id": "4dc7e8ece9275526310127f7", - "pos": 32768, - "type": "check", - "name": "Server side support for member URLs" - }, { - "_id": "4dc7e8f6e92755263101290f", - "pos": 49152, - "type": "check", - "name": "Server side support for board URLs" - }, { - "_id": "4dc9379612f8cee93501af53", - "pos": 65536, - "type": "check", - "name": "Backwards compatible hash version" - }, { - "_id": "4dc937bb12f8cee93501b18b", - "pos": 98304, - "type": "check", - "name": "quickload for members" - }, { - "_id": "4dc93f5b12f8cee9350270af", - "pos": 114688, - "type": "check", - "name": "backfill username" - }, { - "_id": "4dc951466a4b5c603601f461", - "pos": 131072, - "type": "check", - "name": "enforce username select on account create" - }, { - "_id": "4dc9929ee236cc1e370c0cd3", - "pos": 147456, - "type": "check", - "name": "card URLs" - }], - "_id": "4dc7e8cde927552631011f32", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dc849a6ba75abdf3205d35a", - "pos": 16384, - "type": "check", - "name": "Verify use of tokens in ajaxRpc" - }], - "_id": "4dc84984ba75abdf3205c95e", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dcaa2125c09b74e3e03bbf7", - "pos": 16384, - "type": "check", - "name": "Give another user co-ownership of a board" - }, { - "_id": "4dcaa2295c09b74e3e03bd96", - "pos": 32768, - "type": "check", - "name": "Remove your own ownership if there is a remaining owner" - }], - "_id": "4dcaa2085c09b74e3e03b00f", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dcc42565dcb84024615584d", - "pos": 16384, - "type": "check", - "name": "schema" - }, { - "_id": "4dcc425b5dcb8402461558e8", - "pos": 32768, - "type": "check", - "name": "action wiring" - }, { - "_id": "4dcc42695dcb840246155a72", - "pos": 65536, - "type": "check", - "name": "immediate vote feedback" - }, { - "_id": "4dcc42875dcb840246156d68", - "pos": 81920, - "type": "check", - "name": "action display" - }, { - "_id": "4dcd3c585dcb840246221dee", - "pos": 98304, - "type": "check", - "name": "badges" - }], - "_id": "4dcc41e25dcb84024614df30", - "name": "Checklist" - }, { - "_id": "4dcd6da85dcb84024629626c", - "checkItems": [{ - "_id": "4dcd6dd45dcb8402462973a1", - "pos": 49152, - "type": "check", - "name": "Readable URLs" - }, { - "_id": "4dcd6de25dcb84024629750d", - "pos": 65536, - "type": "check", - "name": "PushState instead of /#" - }, { - "_id": "4dcd6df95dcb8402462976db", - "pos": 81920, - "type": "check", - "name": "Semantic Markup (good use of p tags, link text, img alt attributes)" - }, { - "_id": "4dcd6dfc5dcb840246297783", - "pos": 98304, - "type": "check", - "name": "Meta description" - }, { - "_id": "4dcd6e005dcb84024629783c", - "pos": 114688, - "type": "check", - "name": "Descriptive Page Titles" - }], - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dcd77c05dcb8402462d836d", - "pos": 16384, - "type": "check", - "name": "Skinny badge" - }, { - "_id": "4dcd77c95dcb8402462d845d", - "pos": 32768, - "type": "check", - "name": "Vote button state" - }], - "_id": "4dcd77a75dcb8402462d69ee", - "name": "Design Touch Ups" - }, { - "checkItems": [{ - "_id": "4dcd96575dcb84024634b11e", - "pos": 16384, - "type": "check", - "name": "Propagate new commenting members (the member, not the idMembersRemoved) as soon as they comment" - }, { - "_id": "4dcd96655dcb84024634b29a", - "pos": 32768, - "type": "check", - "name": "Vote actions not showing up on cards" - }], - "_id": "4dcd96405dcb84024634a0f8", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dd11ecd5dcb840246509361", - "pos": 16384, - "type": "check", - "name": "delete attachments" - }, { - "_id": "4dd11ee45dcb84024650d68a", - "pos": 32768, - "type": "check", - "name": "badge for attachments" - }, { - "_id": "4dd122bf5dcb84024651be40", - "pos": 49152, - "type": "check", - "name": "icon for attachments badge" - }, { - "_id": "4dd1239b5dcb8402465202a6", - "pos": 65536, - "type": "check", - "name": "view attachments inside trellis?" - }, { - "_id": "4dd12d995dcb840246560562", - "pos": 81920, - "type": "check", - "name": "attach multiple files at once" - }, { - "_id": "4dd137315dcb84024659ea3c", - "pos": 98304, - "type": "check", - "name": "instant update of board action list when attachment is added" - }], - "_id": "4dd11ec95dcb840246508972", - "name": "Checklist" - }, { - "checkItems": [{ - "_id": "4dd138a85dcb8402465aad37", - "pos": 16384, - "type": "check", - "name": "IE 9 choke on console.log" - }, { - "_id": "4dd138e65dcb8402465ad86d", - "pos": 32768, - "type": "check", - "name": "Can add a due date from a public comment [brett]" - }, { - "_id": "4dd139025dcb8402465b4c99", - "pos": 49152, - "type": "check", - "name": "public viewers can see \"add checklist item\"" - }, { - "_id": "4dd1391a5dcb8402465b4eac", - "pos": 65536, - "type": "check", - "name": "public viewers get JS error when trying to open member menu" - }, { - "_id": "4dd13d5e5dcb8402465efad0", - "pos": 81920, - "type": "check", - "name": "don't use cursor:pointer on checklist items for public viewers" - }, { - "_id": "4dd144e35dcb840246630e4e", - "pos": 98304, - "type": "check", - "name": "color vote badge when it includes a vote from you [daniel]" - }, { - "_id": "4dd146dd5dcb8402466410ae", - "pos": 114688, - "type": "check", - "name": "Adding an attachment doesn't instantly give a card an attachment badge [brett]" - }], - "_id": "4dd1389c5dcb8402465a7bc9", - "name": "Checklist" - }, { - "_id": "4dd139ce5dcb8402465bcbf9", - "checkItems": [{ - "_id": "4dd139dd5dcb8402465c3cd5", - "pos": 32768, - "type": "check", - "name": "Can't quick enter checklist items on all browsers" - }, { - "_id": "4dd139ed5dcb8402465c65e8", - "pos": 49152, - "type": "check", - "name": "hide attachments upload button from iOS devices" - }, { - "_id": "4dd13a3c5dcb8402465d3cdc", - "pos": 65536, - "type": "check", - "name": "Button active state \"sticks\" on iOS" - }], - "name": "Checklist" - }, { - "_id": "4dd163620bd1b83a5b0e7c00", - "checkItems": [{ - "_id": "4dd1638b0bd1b83a5b0e8abe", - "name": "Labels button and pop-over in card detail [bobby]", - "pos": 32768, - "type": "check" - }, { - "_id": "4dd163b10bd1b83a5b0e991f", - "name": "Palette [bobby]", - "pos": 49152, - "type": "check" - }, { - "_id": "4dd28be8728b921a5d1fbb42", - "pos": 65536, - "type": "check", - "name": "HTML/CSS" - }], - "name": "Design Checklist" - }, { - "_id": "4dd177f40bd1b83a5b1c57a9", - "checkItems": [{ - "_id": "4dd178390bd1b83a5b1c6760", - "pos": 16384, - "type": "check", - "name": "Spawn multiple processes: Cluster?" - }, { - "_id": "4dd178d60bd1b83a5b1cc066", - "name": "PubSub: Redis", - "pos": 32768, - "type": "check" - }, { - "_id": "4dd69b0d7165bb5c7243f933", - "name": "Heartbeat / Sessions", - "pos": 49152, - "type": "check" - }, { - "_id": "4dda546b19e692e0053d9be5", - "pos": 65536, - "type": "check", - "name": "Go to a single minify step across all processes (maybe on release)" - }, { - "_id": "4ddac01e566cceb30f14e1c2", - "pos": 81920, - "type": "check", - "name": "Redis on trellisny1" - }, { - "_id": "4ddd1ef993234c0814377408", - "pos": 114688, - "type": "check", - "name": "ajax RPC consistency" - }], - "name": "Checklist" - }, { - "_id": "4dd28ae9728b921a5d1e1249", - "checkItems": [{ - "_id": "4dd28af0728b921a5d1e2295", - "pos": 16384, - "type": "check", - "name": "Way to clear due date" - }, { - "_id": "4dd28afb728b921a5d1e246b", - "pos": 32768, - "type": "check", - "name": "Add due dates from card actions (pop over menu)" - }, { - "_id": "4dd28b15728b921a5d1e267a", - "pos": 49152, - "type": "check", - "name": "Fuzzy dates" - }], - "name": "Checklist" - }, { - "_id": "4dd2da8d728b921a5d30c42b", - "checkItems": [{ - "_id": "4dd2da93728b921a5d30d50e", - "pos": 16384, - "type": "check", - "name": "Get a real cert" - }, { - "_id": "4dd2dab1728b921a5d30d6e3", - "pos": 32768, - "type": "check", - "name": "Use an options parser instead of the current crazy long positional opts" - }, { - "_id": "4dd2dab6728b921a5d30d7d9", - "pos": 49152, - "type": "check", - "name": "Test like crazy" - }, { - "_id": "4dd2dac4728b921a5d30d8fb", - "pos": 65536, - "type": "check", - "name": "modify start.sh to use ssl" - }, { - "_id": "4dd2ddf6728b921a5d316f84", - "pos": 81920, - "type": "check", - "name": "node 0.4.7 running on trellisny1" - }, { - "_id": "4dd50b2bb9a905d36627f88b", - "pos": 98304, - "type": "check", - "name": "key needs to be readable by trellis user." - }], - "name": "Checklist" - }, { - "_id": "4dd44cdeb9a905d3661bc337", - "checkItems": [{ - "_id": "4dd44ce3b9a905d3661bd52e", - "pos": 16384, - "type": "check", - "name": "public/private" - }, { - "_id": "4dd44ce5b9a905d3661bd620", - "pos": 32768, - "type": "check", - "name": "voting" - }, { - "_id": "4dd44ce7b9a905d3661bd714", - "pos": 49152, - "type": "check", - "name": "public comments" - }, { - "_id": "4dd44d01b9a905d3661bd9d8", - "pos": 81920, - "type": "check", - "name": "sidebar - members" - }, { - "_id": "4dd44d11b9a905d3661bdb11", - "pos": 98304, - "type": "check", - "name": "sidebar - board actions" - }, { - "_id": "4dd44d17b9a905d3661bdc8f", - "pos": 114688, - "type": "check", - "name": "sidebar - activity" - }, { - "_id": "4dd44d1bb9a905d3661bdd96", - "pos": 131072, - "type": "check", - "name": "list guide" - }], - "name": "Checklist" - }, { - "_id": "4dd67bda7165bb5c723c2d49", - "checkItems": [{ - "_id": "4dd67bf47165bb5c723c402c", - "pos": 16384, - "type": "check", - "name": "Fix flashsockets in the SSL case - they get flaky, esp. with multiple browser windows open" - }, { - "_id": "4dd67c207165bb5c723c42d9", - "pos": 32768, - "type": "check", - "name": "The flash policy server is turned off for multi-process trellis, because when every trellis tries to start it up there's a port conflict" - }], - "name": "Checklist" - }, { - "_id": "4ddeb510a9a2bd055c1337e0", - "checkItems": [{ - "_id": "4ddeb525a9a2bd055c134a2e", - "pos": 16384, - "type": "check", - "name": "cards" - }, { - "_id": "4ddeb528a9a2bd055c134b56", - "pos": 32768, - "type": "check", - "name": "checklists" - }, { - "_id": "4ddeb529a9a2bd055c134c64", - "pos": 49152, - "type": "check", - "name": "lists" - }, { - "_id": "4ddeb52ba9a2bd055c134d82", - "pos": 65536, - "type": "check", - "name": "boards" - }, { - "_id": "4ddeb52da9a2bd055c134ea2", - "pos": 81920, - "type": "check", - "name": "members" - }, { - "_id": "4ddeb53ba9a2bd055c13501e", - "pos": 98304, - "type": "check", - "name": "board invites" - }], - "name": "Checklist" - }, { - "_id": "4ddeb83fa9a2bd055c14cfe5", - "checkItems": [{ - "_id": "4ddeb853a9a2bd055c14e131", - "name": "Refactor sessions.js", - "pos": 16384, - "type": "check" - }, { - "_id": "4ddf9ce8478463e761026e64", - "pos": 49152, - "type": "check", - "name": "Fix notification race condition" - }, { - "_id": "4ddfa076478463e76103790e", - "name": "Get (correct) board watcher count back", - "pos": 65536, - "type": "check" - }, { - "_id": "4de289955c292e601a00d8a2", - "pos": 98304, - "type": "check", - "name": "node-openid stores associations per process - we need to fix that." - }, { - "_id": "4dffa580079f66be4b04396f", - "pos": 114688, - "type": "check", - "name": "over-publishing redis notifications" - }, { - "_id": "4e01e5214a2956844303cbc3", - "pos": 131072, - "type": "check", - "name": "/enabled.html to activate/deactivate server" - }, { - "_id": "4e0232408d64cbf783026e0a", - "pos": 147456, - "type": "check", - "name": "restore us to multiprocess, then to multiserver" - }], - "name": "Checklist" - }, { - "_id": "4ddfbbcf478463e7610a3621", - "checkItems": [{ - "_id": "4ddfbbd7478463e7610a41bd", - "pos": 16384, - "type": "check", - "name": "schema.js: 790" - }, { - "_id": "4ddfbc40478463e7610a586e", - "pos": 32768, - "type": "check", - "name": "account.js: 108" - }], - "name": "Checklist" - }, { - "_id": "4de009d99669af6c6902b730", - "checkItems": [{ - "_id": "4de009fb9669af6c6902bd81", - "pos": 16384, - "type": "check", - "name": "IE \"Socket not writable\" when trying to get ie.css on fresh browser login in IE9 in test" - }, { - "_id": "4de00a089669af6c6902bf49", - "pos": 32768, - "type": "check", - "name": "IE login laps in production" - }], - "name": "Checklist" - }, { - "_id": "4de3f6ae5c292e601a12e70f", - "checkItems": [{ - "_id": "4de3f6bc5c292e601a12f0d8", - "pos": 16384, - "type": "check", - "name": "patch openid for async assoc storage" - }, { - "_id": "4de3f6cb5c292e601a12f21e", - "pos": 32768, - "type": "check", - "name": "trellis change to use Redis to store assocs" - }], - "name": "Checklist" - }, { - "checkItems": [], - "_id": "4de4e54df38ea2ed1f02d946", - "name": "Checklist" - }, { - "_id": "4de53731c1955d252209ffc8", - "checkItems": [{ - "_id": "4de5375cc1955d25220a17c7", - "name": "account.js [Aaron]", - "pos": 16384, - "type": "check" - }, { - "_id": "4de5375ec1955d25220a1908", - "name": "ajaxRpc.js [Aaron]", - "pos": 32768, - "type": "check" - }, { - "_id": "4de5376bc1955d25220a1ba9", - "name": "packager.js (Ian)", - "pos": 49152, - "type": "check" - }, { - "_id": "4de53770c1955d25220a1cee", - "name": "permissions.js (Ian)", - "pos": 65536, - "type": "check" - }, { - "_id": "4de53775c1955d25220a1e38", - "name": "rpc.js (daniel)", - "pos": 81920, - "type": "check" - }, { - "_id": "4de5377ac1955d25220a1f84", - "name": "schema.js (daniel)", - "pos": 98304, - "type": "check" - }, { - "_id": "4de5377fc1955d25220a20cf", - "name": "sessions.js [Brett]", - "pos": 114688, - "type": "check" - }, { - "_id": "4de53783c1955d25220a22b4", - "name": "sockets.js (Ian)", - "pos": 131072, - "type": "check" - }], - "name": "/server" - }, { - "_id": "4de5373ec1955d25220a0b89", - "checkItems": [{ - "_id": "4de538f2c1955d25220a5985", - "name": "actionfilter.js - Not used right now, don't worry about it.", - "pos": 16384, - "type": "check" - }, { - "_id": "4de538f5c1955d25220a5ad6", - "name": "browser.js [Aaron]", - "pos": 32768, - "type": "check" - }, { - "_id": "4de538f7c1955d25220a5c26", - "name": "dates.js - see daniel first [Aaron]", - "pos": 49152, - "type": "check" - }, { - "_id": "4de538fdc1955d25220a5f8b", - "name": "search.js - Not used right now, don't worry about it.", - "pos": 81920, - "type": "check" - }], - "name": "/static/js/" - }, { - "_id": "4de53c77c1955d25220b2bad", - "checkItems": [{ - "_id": "4de53c7ec1955d25220b3770", - "name": "trellis.js [Aaron]", - "pos": 16384, - "type": "check" - }], - "name": "/" - }, { - "_id": "4de695be3ecfb79a26086cfa", - "checkItems": [{ - "_id": "4de695d23ecfb79a260881e2", - "name": "closureCompiler.js (Ian)", - "pos": 16384, - "type": "check" - }, { - "_id": "4de695da3ecfb79a26088348", - "name": "bundle.js [brett]", - "pos": 32768, - "type": "check" - }, { - "_id": "4de695de3ecfb79a26088546", - "name": "gzipResponse.js (brett)", - "pos": 49152, - "type": "check" - }, { - "_id": "4de695f53ecfb79a26088a5a", - "name": "auth.js (Ian)", - "pos": 65536, - "type": "check" - }, { - "_id": "4de90b954cd033ab2d196a21", - "pos": 81920, - "type": "check", - "name": "emailusers/emailusers.js (brett)" - }], - "name": "/modules" - }, { - "_id": "4de8f7474cd033ab2d1431cd", - "checkItems": [{ - "_id": "4de8f7524cd033ab2d146f97", - "pos": 16384, - "type": "check", - "name": "Org profile" - }, { - "_id": "4de8f7594cd033ab2d1475e4", - "pos": 32768, - "type": "check", - "name": "Create org" - }, { - "_id": "4de8f7704cd033ab2d147d18", - "pos": 49152, - "type": "check", - "name": "List of orgs in member profile" - }, { - "_id": "4de8f77c4cd033ab2d147f5b", - "pos": 65536, - "type": "check", - "name": "List of org boards in member profile" - }, { - "_id": "4de8f7824cd033ab2d1480dd", - "name": "Preferences: perms for features, visibility", - "pos": 81920, - "type": "check" - }, { - "_id": "4de8f7c44cd033ab2d14982f", - "pos": 98304, - "type": "check", - "name": "New board: option to make part of org" - }, { - "_id": "4de8f8244cd033ab2d149f0c", - "name": "Move/add board to org (in board preferences)", - "pos": 114688, - "type": "check" - }, { - "_id": "4de8f82a4cd033ab2d14a096", - "name": "Manage org members page", - "pos": 131072, - "type": "check" - }, { - "_id": "4de94253d7b3339b2f11cf9b", - "pos": 147456, - "type": "check", - "name": "Org account page" - }, { - "_id": "4df8ed9adc894c716d1ccc78", - "pos": 163840, - "type": "check", - "name": "Enforce that orgs and members can't have the same name: first claimer wins" - }, { - "_id": "4e035aba8d64cbf7834194d3", - "pos": 180224, - "type": "check", - "name": "'Add Board' from the org page" - }, { - "_id": "4e035aeb8d64cbf78341c4ff", - "pos": 196608, - "type": "check", - "name": "Email template changes for org invite" - }, { - "_id": "4e035afa8d64cbf78341d835", - "pos": 212992, - "type": "check", - "name": "Allow you to join Trellis if you're invited to an org" - }, { - "_id": "4e035b978d64cbf783420ab1", - "pos": 229376, - "type": "check", - "name": "Make org boards show up in 'Boards' menu" - }, { - "_id": "4e035c888d64cbf783424ea0", - "pos": 245760, - "type": "check", - "name": "Feels like an organization header on the boards page should take me to the page for the org" - }, { - "_id": "4e035d088d64cbf7834269e4", - "pos": 262144, - "type": "check", - "name": "Consolidate joinBoard / joinOrganization templates" - }, { - "_id": "4e035f718d64cbf78342d8f3", - "pos": 278528, - "type": "check", - "name": "With Ian, figure out how to merge board and org invitation mgmt more" - }], - "name": "UI" - }, { - "_id": "4df21c86f07016d15a01b030", - "checkItems": [{ - "_id": "4df21c91f07016d15a01c8eb", - "pos": 16384, - "type": "check", - "name": "Get trellis running on one FreeBSD server" - }, { - "_id": "4df21cadf07016d15a01d6c2", - "pos": 32768, - "type": "check", - "name": "Get both servers running pointing to the same mongo and redis" - }, { - "_id": "4df21ccaf07016d15a01e471", - "pos": 49152, - "type": "check", - "name": "Load balance" - }, { - "_id": "4df21cd7f07016d15a01f13c", - "pos": 65536, - "type": "check", - "name": "Test new setup" - }, { - "_id": "4df21ce4f07016d15a020b6d", - "name": "Flip DNS and adjust NAT [shawn] Tomorrow first thing.", - "pos": 98304, - "type": "check" - }, { - "_id": "4df25601839542cf5a106682", - "pos": 114688, - "type": "check", - "name": "Build node_modules for BSD 8.2" - }, { - "_id": "4df60eeac204e79d5d2a3713", - "pos": 131072, - "type": "check", - "name": "FreeBSD build machine" - }, { - "_id": "4df6332b8676f5a05d30cc80", - "name": "Fix node.js FreeBSD link issue to get hiredis, forever, and native bson parser working again. http://www.freebsd.org/cgi/query-pr.cgi?pr=157875", - "pos": 147456, - "type": "check" - }, { - "_id": "4df7bd69e5c8fa736d0b4323", - "pos": 163840, - "type": "check", - "name": "Build with kqueue" - }, { - "_id": "4df7c062e5c8fa736d0b8169", - "pos": 180224, - "type": "check", - "name": "re-enable backup-on-push in the bsd branch once we have perms" - }, { - "_id": "4df8be3edc894c716d12102f", - "name": "Issue pull request to ry for kqueue patch. https://github.com/joyent/node/pull/1186", - "pos": 196608, - "type": "check" - }, { - "_id": "4df8e529dc894c716d1a308c", - "pos": 212992, - "type": "check", - "name": "sockets are disconnected after a few seconds when going through HAProxy[shawn]" - }, { - "_id": "4df90c7fdc894c716d21a98d", - "name": "Allow trellisny3 and ny2 to connect to trellisny1's mongo and redis so that we can move servers without burning the ships. [shawn] http://our.fogbugz.com/default.asp?2076170", - "pos": 229376, - "type": "check" - }, { - "_id": "4df91169dc894c716d21eea7", - "name": "Send keepalives over open sockets every 30 minutes, b/c HAProxy will time out idle connections after an hour.[brett]", - "pos": 245760, - "type": "check" - }, { - "_id": "4dfa3772ee196e34f901c9e3", - "pos": 262144, - "type": "check", - "name": "When connected to trellis on the new servers: you do something and don't see it refected in the activity feed" - }, { - "_id": "4dfa676b959e5c5cfc055192", - "pos": 278528, - "type": "check", - "name": "Cut over to redis on trellisny2" - }], - "name": "Checklist" - }, { - "_id": "4df69f0e8676f5a05d39da78", - "checkItems": [{ - "_id": "4df6a02d8676f5a05d3a0f4f", - "pos": 16384, - "type": "check", - "name": "Clicking any input on /login redirects to /authenticate, expected /confirmedNewMember for create account" - }, { - "_id": "4df6a0e08676f5a05d3a2169", - "pos": 32768, - "type": "check", - "name": "Whitelisted, non-google email address (I tried yahoo) redirect to '/login?returnUrl=/authenticate' on create account." - }, { - "_id": "4df6a4508676f5a05d3a4b8e", - "name": "Attempting to sign in with google goes to /verify, then immediately redirects to /login?returnUrl=/verify (broken on fresh db, worked on old db)", - "pos": 49152, - "type": "check" - }], - "name": "Bugz" - }, { - "_id": "4df8bc8ddc894c716d110817", - "checkItems": [{ - "_id": "4df8bc99dc894c716d111ec9", - "pos": 16384, - "type": "check", - "name": "Test env on trellis-build" - }, { - "_id": "4df8bcafdc894c716d112b66", - "name": "scripts to start server and blank DB", - "pos": 32768, - "type": "check" - }, { - "_id": "4df8bcc2dc894c716d11373c", - "pos": 49152, - "type": "check", - "name": "VPN" - }, { - "_id": "4df8bccedc894c716d1143ce", - "pos": 65536, - "type": "check", - "name": "account on trellis-build" - }, { - "_id": "4df8bcd2dc894c716d114f8d", - "pos": 81920, - "type": "check", - "name": "instructions" - }, { - "_id": "4df8c75adc894c716d143849", - "pos": 98304, - "type": "check", - "name": "ourdot access" - }, { - "_id": "4dfb8ccae01b09000006e102", - "pos": 114688, - "type": "check", - "name": "script to hg pull/up" - }], - "name": "Checklist" - }, { - "_id": "4dfb6db01c2ab8000003041f", - "checkItems": [{ - "_id": "4dfb6dbb1c2ab80000031d46", - "pos": 16384, - "type": "check", - "name": "Close board" - }, { - "_id": "4dfb6dbf1c2ab80000032b7b", - "pos": 32768, - "type": "check", - "name": "change name" - }, { - "_id": "4dfb6dc31c2ab800000338e3", - "pos": 49152, - "type": "check", - "name": "change preferences" - }], - "name": "Checklist" - }, { - "_id": "4dff859729bde2224901cc9e", - "checkItems": [{ - "_id": "4dff85b229bde2224901eaaa", - "pos": 16384, - "type": "check", - "name": "People are listed as 'active' who haven't logged in for days" - }, { - "_id": "4dff85c629bde2224901fa21", - "pos": 32768, - "type": "check", - "name": "only 4 procs are showing up in liveprocs" - }, { - "_id": "4dff85f029bde22249020b47", - "pos": 49152, - "type": "check", - "name": "status entries without a liveprocs entry are still not being deleted" - }, { - "_id": "4dff864b29bde222490226f5", - "pos": 65536, - "type": "check", - "name": "however, we do not see any status entries with an incorrect status in Redis" - }], - "name": "Checklist" - }, { - "_id": "4dffa67d079f66be4b04bb5a", - "checkItems": [{ - "_id": "4dffa688079f66be4b04da43", - "pos": 16384, - "type": "check", - "name": "Better behavior when setting password for existing account" - }, { - "_id": "4dffa68f079f66be4b04ea2f", - "pos": 32768, - "type": "check", - "name": "No duplicate-email accounts" - }, { - "_id": "4dffa69f079f66be4b04fa20", - "pos": 49152, - "type": "check", - "name": "Feedback that password change occurred" - }, { - "_id": "4dffa6ad079f66be4b050ae8", - "pos": 65536, - "type": "check", - "name": "Feedback that the username or password was incorrect on login" - }, { - "_id": "4e00c20c079f66bb4b0f1148", - "pos": 81920, - "type": "check", - "name": "Fix styles for incorrect login message" - }, { - "_id": "4e00d4ef079f66bc4b154c82", - "pos": 98304, - "type": "check", - "name": "email account confirmation" - }, { - "_id": "4e00dffb079f66be4b14d9a0", - "pos": 114688, - "type": "check", - "name": "allow you to create a non-openid user with a password" - }, { - "_id": "4e00f93117baf6ee6603162f", - "pos": 131072, - "type": "check", - "name": "forgot password page" - }, { - "_id": "4e09f16685ad212f9adcc3c3", - "pos": 147456, - "type": "check", - "name": "Allow account creation for any email with invite code" - }, { - "_id": "4e0cc02737796f0000214c74", - "pos": 163840, - "type": "check", - "name": "Dial with CR comment from http://our.fogbugz.com/kiln/Review/2075267" - }, { - "_id": "4e14beb29df22bbd48037a16", - "name": "No account confirmation [deferred for now]", - "pos": 180224, - "type": "check" - }], - "name": "Checklist" - }, { - "_id": "4e0dd9d6ca68f50000034cc7", - "checkItems": [{ - "_id": "4e0dd9dcca68f50000036f68", - "pos": 16384, - "type": "check", - "name": "Can't reopen closed boards" - }, { - "_id": "4e0dd9f4ca68f50000039479", - "pos": 49152, - "type": "check", - "name": "When you DO reopen a closed board from a different page, it's blank until you reload" - }, { - "_id": "4e0dd9fcca68f5000003a6cd", - "pos": 65536, - "type": "check", - "name": "Reopening a board should just take you to the board" - }], - "name": "Checklist" - }, { - "checkItems": [], - "_id": "4e1457780855bfafa8020b9d", - "name": "Checklist" - }, { - "_id": "4e1457790855bfafa8022037", - "checkItems": [{ - "_id": "4e1457ad0855bfafa802c424", - "pos": 16384, - "type": "check", - "name": "Board Preferences -> Better alignment/spacing on add to org" - }, { - "_id": "4e14582e0855bfafa8033196", - "name": "Some way to get to the organization's page from the board (for org members)", - "pos": 32768, - "type": "check" - }, { - "_id": "4e146ba79b22b2b94800e2cb", - "name": "Make org name show up in 'Boards' menu", - "pos": 49152, - "type": "check" - }, { - "_id": "4e146bbc8e237d0eaa00fa9c", - "pos": 65536, - "type": "check", - "name": "With Ian, figure out how to merge board and org invitation mgmt more" - }, { - "_id": "4e146bc6c3dce0b84801a9cd", - "pos": 81920, - "type": "check", - "name": "Member status changes update immediately" - }, { - "_id": "4e147dda9b22b2ba480955f2", - "pos": 98304, - "type": "check", - "name": "Admin page: org stats" - }, { - "_id": "4e14a160018bc307aa072caa", - "pos": 114688, - "type": "check", - "name": "Only allow org admins to see :org/members and :org/account" - }, { - "_id": "4e14b508b809c7dbab083e73", - "pos": 131072, - "type": "check", - "name": "Public view of org (org and private boards hidden to non-orgers, members are shown)" - }], - "name": "Checklist" - }, { - "checkItems": [], - "_id": "4e17350dec9833696c04aa79", - "name": "Checklist" - }, { - "_id": "4e17350fec9833696c04c94a", - "checkItems": [{ - "_id": "4e173527ec9833696c0524f7", - "pos": 16384, - "type": "check", - "name": "Make sure non-socket-connected browsers catch the upgrade" - }, { - "_id": "4e17352dec9833696c053a3b", - "pos": 32768, - "type": "check", - "name": "reconnect gracefully" - }, { - "_id": "4e17353bec9833696c054f8a", - "pos": 49152, - "type": "check", - "name": "detect version bump and gently ask the user to click to upgrade" - }, { - "_id": "4e28af81ce64d1930a014150", - "pos": 83360, - "type": "check", - "name": "Sync subscribed models on socket-connected browsers" - }], - "name": "Checklist" - }, { - "_id": "4e1b53e4274d60b9dd06b281", - "checkItems": [{ - "_id": "4e1b53f5274d60b9dd071ada", - "pos": 16384, - "type": "check", - "name": "Notifications" - }, { - "_id": "4e1b53fc274d60b9dd072d6b", - "pos": 32768, - "type": "check", - "name": "Invitation" - }, { - "_id": "4e1b5404274d60b9dd073ff1", - "pos": 49152, - "type": "check", - "name": "Org Permission Level" - }, { - "_id": "4e1b5407274d60b9dd07526c", - "pos": 65536, - "type": "check", - "name": "Archive" - }, { - "_id": "4e1bce84a5a5a4000003c761", - "pos": 81920, - "type": "check", - "name": "Search" - }, { - "_id": "4e1bd069a5a5a4000003fcab", - "pos": 98304, - "type": "check", - "name": "Label (large)" - }], - "name": "Icons" - }, { - "checkItems": [], - "_id": "4e1b53e5274d60b9dd06cd0d", - "name": "Checklist" - }, { - "_id": "4e1c52928d677cfe8300697d", - "checkItems": [{ - "_id": "4e1c52ad8d677cfe83008e73", - "pos": 16384, - "type": "check", - "name": "Still have to keep dragging the card to keep it scrolling -- holding it over the bottom or top of the list doesn't scroll" - }, { - "_id": "4e1c52bf8d677cfe8300a1d4", - "pos": 32768, - "type": "check", - "name": "Single-col still doesn't scroll" - }, { - "_id": "4e1dcb277b2050df84026134", - "pos": 50033, - "type": "check", - "name": "ie doesn't scroll" - }], - "name": "Checklist" - }, { - "_id": "4e1c959c9a872d028402dbb8", - "checkItems": [{ - "_id": "4e1c95ac9a872d0284030358", - "pos": 16384, - "type": "check", - "name": "the \"Archive\" button in the sidebar looks like it might archive the board" - }, { - "_id": "4e1c95b49a872d028403183e", - "pos": 32768, - "type": "check", - "name": "closed cards say \"reopen\"" - }, { - "_id": "4e1c96489a872d0284046c6c", - "pos": 65536, - "type": "check", - "name": "list menu says \"close list\"" - }, { - "_id": "4e1c96566adf53fa83160ba6", - "pos": 81920, - "type": "check", - "name": "hover over archive button on card says \"Close card\"" - }, { - "_id": "4e1c967b9a872d0284048163", - "pos": 98304, - "type": "check", - "name": "The long-hold menu uses the old close icon" - }], - "name": "Checklist" - }, { - "_id": "4e1d7fb662429ee21c02f483", - "checkItems": [{ - "_id": "4e1d7fbe62429ee21c031e63", - "pos": 17314, - "type": "check", - "name": "Show date uploaded" - }, { - "_id": "4e1d7fc362429ee21c03346f", - "pos": 34198, - "type": "check", - "name": "Most recent file at top" - }, { - "_id": "4e1d7fd162429ee21c034a7d", - "pos": 51067, - "type": "check", - "name": "Delete attachments" - }, { - "_id": "4e1d7fdf62429ee21c03608d", - "pos": 67484, - "type": "check", - "name": "Show previews of attachment in action?" - }, { - "_id": "4e1dddbd802ec6e81c057d93", - "pos": 84038, - "type": "check", - "name": "Fix previews for deleted attachments" - }], - "name": "Checklist" - }, { - "_id": "4e1f0b467c741f95300199a6", - "checkItems": [{ - "_id": "4e1f0b787c741f953001ca06", - "name": "Add helper text to org section of 'new board' page, include link to create org page.", - "pos": 16415, - "type": "check" - }, { - "_id": "4e1f0bdf7c741f9530024340", - "name": "Add create org link on member boards page", - "pos": 33562, - "type": "check" - }], - "name": "Checklist" - }, { - "_id": "4e20882da43ec975a00594c0", - "checkItems": [{ - "_id": "4e208831a43ec975a005c1c2", - "pos": 16520, - "type": "check", - "name": "Profile of others has incomplete actions list" - }, { - "_id": "4e208836a43ec975a005d968", - "pos": 33602, - "type": "check", - "name": "Initial board load prefs" - }, { - "_id": "4e208851a43ec975a005f115", - "pos": 50465, - "type": "check", - "name": "No document may grow without bound or we will eventually bump MongoDB's 16MB limit" - }], - "name": "Checklist" - }, { - "checkItems": [], - "_id": "4e31abbd44e04eb4f00c7627", - "name": "Checklist" - }, { - "_id": "4e31abbe44e04eb4f00c96fe", - "checkItems": [{ - "_id": "4e31abd544e04eb4f00cc734", - "pos": 16928, - "type": "check", - "name": "Client takes a long time to figure out it's not connected" - }], - "name": "Checklist" - }, { - "checkItems": [], - "_id": "4e36b73a115cc20000019c3a", - "name": "Checklist" - }, { - "_id": "4e723f7dec7bba0000151903", - "checkItems": [{ - "_id": "4e723f8aec7bba0000155231", - "pos": 17392, - "type": "check", - "name": "Become invisible to people who don't know my email address" - }, { - "_id": "4e723f9dec7bba0000159cb6", - "pos": 34459, - "type": "check", - "name": "Become invisible to people who I don't share a board/org with." - }, { - "_id": "4e723fb1eb752c26d615d10b", - "pos": 51840, - "type": "check", - "name": "Make it so outsiders can't see what orgs I belong to." - }], - "name": "Checklist" - }, { - "_id": "4e7a20cb07fb4fc4c2019fc9", - "checkItems": [{ - "_id": "4e7a20cf4003bbbbc200af97", - "pos": 33965, - "type": "check", - "name": "2" - }, { - "_id": "4e7a20d06573bfc3c200013d", - "pos": 51219, - "type": "check", - "name": "3" - }, { - "_id": "4e7a20d207fb4fc4c201bf51", - "pos": 16825, - "type": "check", - "name": "1" - }, { - "_id": "4e7b97db87f962e71d023066", - "pos": 67767, - "type": "check", - "name": "4" - }], - "name": "Checklist" - }, { - "_id": "4e95e0160fa46da8a6001c46", - "checkItems": [{ - "_id": "4e95e0170fa46da8a6002026", - "pos": 17372, - "type": "check", - "name": "1" - }, { - "_id": "4e95e0180fa46da8a60022a7", - "pos": 34778, - "type": "check", - "name": "2" - }, { - "_id": "4e95e0180fa46da8a600252a", - "pos": 51336, - "type": "check", - "name": "3" - }, { - "_id": "4e95e0180fa46da8a60027af", - "pos": 68195, - "type": "check", - "name": "4" - }, { - "_id": "4e95e0190fa46da8a6002a36", - "pos": 85418, - "type": "check", - "name": "45" - }], - "name": "Checklist" - }, { - "_id": "4edf81719dfadf92ba00043f", - "checkItems": [{ - "_id": "4edf81739dfadf92ba00086e", - "pos": 16681, - "type": "check", - "name": "a" - }, { - "_id": "4edf81749dfadf92ba000afd", - "pos": 33089, - "type": "check", - "name": "b" - }, { - "_id": "4edf81749dfadf92ba000d8e", - "pos": 49707, - "type": "check", - "name": "c" - }, { - "_id": "4edf8194406a1093ba000a7c", - "pos": 66874, - "type": "check", - "name": "d" - }, { - "_id": "4edf8194406a1093ba000d17", - "pos": 83580, - "type": "check", - "name": "e" - }, { - "_id": "4edf8195406a1093ba000fb7", - "pos": 100642, - "type": "check", - "name": "f" - }, { - "_id": "4edf8195406a1093ba001256", - "pos": 117840, - "type": "check", - "name": "g" - }], - "name": "ok" - }, { - "_id": "4edf81a6406a1093ba0019d4", - "checkItems": [{ - "_id": "4edf81b1406a1093ba00210b", - "pos": 16855, - "type": "check", - "name": "neato!" - }], - "name": "oh yeah?" - }, { - "_id": "4ee78a30fd0f210000002a81", - "checkItems": [{ - "_id": "4ee78a36fd0f210000002ea4", - "pos": 16858, - "type": "check", - "name": "Hello" - }], - "name": "Checklist" - }, { - "_id": "4f3182e705a3340b64000c26", - "checkItems": [{ - "_id": "4f3182ea05a3340b640010b0", - "pos": 17025, - "type": "check", - "name": "a" - }, { - "_id": "4f3182eb05a3340b64001690", - "pos": 92449, - "type": "check", - "name": "c" - }, { - "_id": "4f3182eb05a3340b64001983", - "pos": 67076, - "type": "check", - "name": "d" - }, { - "_id": "4f3182ec05a3340b64001c78", - "pos": 83917, - "type": "check", - "name": "e" - }, { - "_id": "4f3182ed05a3340b64001f6f", - "pos": 100981, - "type": "check", - "name": "f" - }, { - "_id": "4f318ed87568566268000753", - "pos": 117775, - "type": "check", - "name": "g" - }], - "name": "Checklist" - }, { - "_id": "4f3182ef05a3340b64002267", - "checkItems": [{ - "_id": "4f3182f105a3340b64002706", - "pos": 16481, - "type": "check", - "name": "1" - }, { - "_id": "4f3182f205a3340b64002a03", - "pos": 33604, - "type": "check", - "name": "2" - }, { - "_id": "4f3182f205a3340b64002d02", - "pos": 50212, - "type": "check", - "name": "3" - }, { - "_id": "4f3182f205a3340b64003003", - "pos": 67495, - "type": "check", - "name": "4" - }, { - "_id": "4f3182f305a3340b64003306", - "pos": 84844, - "type": "check", - "name": "5" - }], - "name": "Checklist" - }, { - "_id": "4f318f5f75685662680020ea", - "checkItems": [{ - "_id": "4f318f6275685662680025a2", - "pos": 17401, - "type": "check", - "name": "a" - }, { - "_id": "4f318f6275685662680028ad", - "pos": 34370, - "type": "check", - "name": "b" - }, { - "_id": "4f318f627568566268002bba", - "pos": 51592, - "type": "check", - "name": "c" - }, { - "_id": "4f318f637568566268002ec9", - "pos": 68597, - "type": "check", - "name": "d" - }, { - "_id": "4f318f6475685662680031da", - "pos": 85739, - "type": "check", - "name": "e" - }, { - "_id": "4f318f6475685662680034ed", - "pos": 102588, - "type": "check", - "name": "f" - }], - "name": "Checklist" - }, { - "_id": "4f357bc7f712566521002a28", - "checkItems": [], - "name": "ije" - }, { - "checkItems": [], - "_id": "4f357bd1f71256652100320f", - "name": "lolz" - }, { - "checkItems": [], - "_id": "4f3a7141e1d0033072000257", - "name": "Checklist" - }, { - "_id": "4f3a7142e1d00330720008d6", - "checkItems": [{ - "_id": "4f3a7146e1d0033072000da8", - "pos": 65536, - "type": "check", - "name": "1" - }, { - "_id": "4f3a7149e1d0033072001225", - "pos": 33102, - "type": "check", - "name": "2" - }, { - "_id": "4f3a714ae1d00330720016a5", - "pos": 49702, - "type": "check", - "name": "3" - }], - "name": "Checklist" - }, { - "_id": "4f3a75b94a2915db72000c7f", - "checkItems": [{ - "_id": "4f3a75c94a2915db72001315", - "pos": 16815, - "type": "check", - "name": "1" - }, { - "_id": "4f3a75cb4a2915db7200179e", - "pos": 33925, - "type": "check", - "name": "2" - }, { - "_id": "4f3a75cc4a2915db72001c2a", - "pos": 50337, - "type": "check", - "name": "3" - }, { - "_id": "4f3a75e54991753c730001d0", - "pos": 67169, - "type": "check", - "name": "4" - }, { - "_id": "4f3a75f64991753c73000d69", - "pos": 84551, - "type": "check", - "name": "5" - }, { - "_id": "4f3a7621814abb4d73001252", - "pos": 101594, - "type": "check", - "name": "6" - }, { - "_id": "4f3a763e814abb4d7300239c", - "pos": 118958, - "type": "check", - "name": "7" - }, { - "_id": "4f3a79b71f2bbfba730001f0", - "pos": 136130, - "type": "check", - "name": "8" - }, { - "_id": "4f3a79d01f2bbfba73000a88", - "pos": 152632, - "type": "check", - "name": "9" - }, { - "_id": "4f3a7a3e1797fc09740005cc", - "pos": 169985, - "type": "check", - "name": "10" - }, { - "_id": "4f3a7ba03893916574004908", - "pos": 187334, - "type": "check", - "name": "11" - }, { - "_id": "4f3a7d296f873c9f74002ce5", - "pos": 204306, - "type": "check", - "name": "12" - }, { - "_id": "4f3a7d296f873c9f7400318f", - "pos": 221278, - "type": "check", - "name": "13" - }, { - "_id": "4f3a7d2a6f873c9f7400363c", - "pos": 238543, - "type": "check", - "name": "14" - }, { - "_id": "4f3a882edf73c6a4410009e9", - "pos": 254942, - "type": "check", - "name": "15" - }], - "name": "Checklist" - }, { - "_id": "4f3a885ddf73c6a441002ce7", - "checkItems": [{ - "_id": "4f3a8860df73c6a441003222", - "pos": 17221, - "type": "check", - "name": "a" - }, { - "_id": "4f3a8861df73c6a441003bd3", - "pos": 50893, - "type": "check", - "name": "c" - }, { - "_id": "4f3a8862df73c6a4410040b0", - "pos": 67457, - "type": "check", - "name": "d" - }, { - "_id": "4f3a8862df73c6a441004590", - "pos": 84067, - "type": "check", - "name": "e" - }, { - "_id": "4f3a8863df73c6a441004a73", - "pos": 100547, - "type": "check", - "name": "f" - }, { - "_id": "4f3a8863df73c6a441004f59", - "name": "grrrrrrrrrrrr", - "pos": 117713.5, - "type": "check" - }, { - "_id": "4f3d35c8e5f5419d10001e50", - "name": "h", - "pos": 66496.5, - "type": "check" - }, { - "_id": "4f425bd3ada835670e02256b", - "pos": 65536, - "type": "check", - "name": "1" - }, { - "name": "h", - "type": "check", - "pos": 134880, - "_id": "4f79f18711b5b71a58000a26" - }], - "name": "Checklister" - }, { - "name": "Checklist", - "_id": "4f711679661dd5ebc5004c86", - "checkItems": [] - }, { - "_id": "4f95b7d74043f7b179006025", - "checkItems": [{ - "name": "30% packet loss", - "type": "check", - "pos": 17398, - "_id": "4f95b7ec4043f7b17900637a" - }, { - "name": "just totally cuts out sometimes", - "type": "check", - "pos": 50968, - "_id": "4f95b7ed4043f7b179006849" - }, { - "name": "REALLY lots of latency", - "type": "check", - "pos": 33898, - "_id": "4f95b7edea9ef48b7c001c8a" - }, { - "name": "6", - "type": "check", - "pos": 152755, - "_id": "4f95b857ea9ef48b7c0021a0" - }, { - "name": "7", - "type": "check", - "pos": 169709, - "_id": "4f95b857ea9ef48b7c00267e" - }, { - "name": "8", - "type": "check", - "pos": 186988, - "_id": "4f95b858ea9ef48b7c002b5f" - }, { - "name": "9", - "type": "check", - "pos": 203481, - "_id": "4f95b858ea9ef48b7c003043" - }, { - "name": "1", - "type": "check", - "pos": 67700, - "_id": "4f95b858ea9ef48b7c00352a" - }, { - "name": "4", - "type": "check", - "pos": 118187, - "_id": "4f95b859ea9ef48b7c003a14" - }, { - "name": "5", - "type": "check", - "pos": 135566, - "_id": "4f95b859ea9ef48b7c003f01" - }, { - "name": "2", - "type": "check", - "pos": 84641, - "_id": "4f95b859ea9ef48b7c0043f1" - }, { - "name": "3", - "type": "check", - "pos": 101678, - "_id": "4f95b85aea9ef48b7c0048e4" - }], - "name": "Checklisterize" - }, { - "_id": "4fa03d6d023c0b2a6b00437d", - "checkItems": [{ - "name": "One", - "type": "check", - "pos": 16384, - "_id": "4fa03d6f023c0b2a6b0048c1" - }, { - "name": "Two", - "type": "check", - "pos": 32768, - "_id": "4fa03d6f023c0b2a6b004db9" - }, { - "name": "Three", - "type": "check", - "pos": 49152, - "_id": "4fa03d70023c0b2a6b0052b4" - }], - "name": "Checklist" - }, { - "_id": "4fa03d79023c0b2a6b0061fc", - "checkItems": [{ - "_id": "4fa03d7d023c0b2a6b007170", - "name": "Six Seven Eight Nine", - "pos": 49152, - "type": "check" - }], - "name": "Checklist" - }] -} diff --git a/benchmarks/clone.js b/benchmarks/clone.js deleted file mode 100644 index 217f115341..0000000000 --- a/benchmarks/clone.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict'; - -const mongoose = require('../'); -const Schema = mongoose.Schema; -const Benchmark = require('benchmark'); - -const DocSchema = new Schema({ - title: String -}); - -const SimpleSchema = new Schema({ - string: { type: String, required: true }, - number: { type: Number, min: 10 } -}); - -const AllSchema = new Schema({ - string: { type: String, required: true }, - number: { type: Number, min: 10 }, - date: Date, - bool: Boolean, - buffer: Buffer, - objectid: Schema.ObjectId, - array: Array, - strings: [String], - numbers: [Number], - dates: [Date], - bools: [Boolean], - buffers: [Buffer], - objectids: [Schema.ObjectId], - docs: { - type: [DocSchema], validate: function() { - return true; - } - }, - s: { nest: String } -}); - -const A = mongoose.model('A', AllSchema); -const a = new A({ - string: 'hello world', - number: 444848484, - date: new Date(), - bool: true, - buffer: Buffer.alloc(0), - objectid: new mongoose.Types.ObjectId(), - array: [4, {}, [], 'asdfa'], - strings: ['one', 'two', 'three', 'four'], - numbers: [72, 6493, 83984643, 348282.55], - dates: [new Date(), new Date(), new Date()], - bools: [true, false, false, true, true], - buffers: [Buffer.from([33]), Buffer.from([12])], - - objectids: [new mongoose.Types.ObjectId()], - docs: [{ title: 'yo' }, { title: 'nowafasdi0fas asjkdfla fa' }], - s: { nest: 'hello there everyone!' } -}); - -const Simple = mongoose.model('Simple', SimpleSchema); -const simple = new Simple({ - string: 'hello world', - number: 444848484 -}); - -new Benchmark.Suite() - .add('Simple', function() { - simple.toObject({ depopulate: true }); - }) - .add('AllSchema', function() { - a.toObject({ depopulate: true }); - }) - .on('cycle', function(evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .run(); -process.memoryUsage(); - -// --trace-opt --trace-deopt --trace-bailout \ No newline at end of file diff --git a/benchmarks/create.js b/benchmarks/create.js deleted file mode 100644 index 5a1bcb533b..0000000000 --- a/benchmarks/create.js +++ /dev/null @@ -1,46 +0,0 @@ -// require('nodetime').profile(); - -'use strict'; - -const mongoose = require('../../mongoose'); -const Benchmark = require('benchmark'); - -const Schema = mongoose.Schema; - -const CheckItem = new Schema({ - name: { type: String }, - type: { type: String }, - pos: { type: Number } -}); - -const Checklist = new Schema({ - name: { type: String }, - checkItems: { type: [CheckItem] } -}); - -const Board = new Schema({ - checklists: { type: [Checklist] } -}); - -const BoardModel = mongoose.model('Board', Board); -const CheckItemModel = mongoose.model('CheckItem', CheckItem); -const doc = require('./bigboard.json'); - -new Benchmark.Suite() - .add('CheckItem', function() { - new CheckItemModel({ - _id: '4daee8a2aae47fe55305eabf', - pos: 32768, - type: 'check', - name: 'delete checklists' - }); - }) - .add('Board', function() { - new BoardModel(doc); - }) - .on('cycle', function(evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .run(); diff --git a/benchmarks/index.js b/benchmarks/index.js deleted file mode 100644 index 90521a52bd..0000000000 --- a/benchmarks/index.js +++ /dev/null @@ -1,151 +0,0 @@ -'use strict'; - -Error.stackTraceLimit = Infinity; -const out = process.argv.length < 3; -function log() { - if (out) { - console.error.apply(console, arguments); - } -} - -const mongoose = require('../'); -const Schema = mongoose.Schema; - -const DocSchema = new Schema({ - title: String -}); - -const AllSchema = new Schema({ - string: String, - number: Number, - date: Date, - bool: Boolean, - buffer: Buffer, - objectid: Schema.ObjectId, - array: Array, - strings: [String], - numbers: [Number], - dates: [Date], - bools: [Boolean], - buffers: [Buffer], - objectids: [Schema.ObjectId], - docs: [DocSchema] -}); - -const A = mongoose.model('A', AllSchema); - -let numdocs = 0; -let totaltime = 0; - -// bench the normal way -// the try building the doc into the document prototype -// and using inheritance and bench that -// -// also, bench using listeners for each subdoc vs one -// listener that knows about all subdocs and notifies -// them. - -function run(label, fn) { - log('running %s', label); - let started = process.memoryUsage(); - let start = new Date; - let total = 10000; - let i = total; - let a; - while (i--) { - a = fn(); - if (i % 2) { - a.toObject({ depopulate: true }); - } else { - if (a._delta) { - a._delta(); - } else { - a.$__delta(); - } - } - } - let time = (new Date - start) / 1000; - totaltime += time; - numdocs += total; - log(label + ' took %d seconds for %d docs (%d dps)', time, total, total / time); - let used = process.memoryUsage(); - let res = {}; - res.rss = used.rss - started.rss; - res.heapTotal = used.heapTotal - started.heapTotal; - res.heapUsed = used.heapUsed - started.heapUsed; - log('change: ', res); - a = res = used = time = started = start = total = i = null; -} - -run('string', function() { - return new A({ - string: 'hello world' - }); -}); -run('number', function() { - return new A({ - number: 444848484 - }); -}); -run('date', function() { - return new A({ - date: new Date - }); -}); -run('bool', function() { - return new A({ - bool: true - }); -}); -run('buffer', function() { - return new A({ - buffer: Buffer.alloc(0) - }); -}); -run('objectid', function() { - return new A({ - objectid: new mongoose.Types.ObjectId() - }); -}); -run('array of mixed', function() { - return new A({ - array: [4, {}, [], 'asdfa'] - }); -}); -run('array of strings', function() { - return new A({ - strings: ['one', 'two', 'three', 'four'] - }); -}); -run('array of numbers', function() { - return new A({ - numbers: [72, 6493, 83984643, 348282.55] - }); -}); -run('array of dates', function() { - return new A({ - dates: [new Date, new Date, new Date] - }); -}); -run('array of bools', function() { - return new A({ - bools: [true, false, false, true, true] - }); -}); -run('array of buffers', function() { - return new A({ - buffers: [Buffer.from([33]), Buffer.from([12])] - }); -}); -run('array of objectids', function() { - return new A({ - objectids: [new mongoose.Types.ObjectId] - }); -}); -run('array of docs', function() { - return new A({ - docs: [{ title: 'yo' }, { title: 'nowafasdi0fas asjkdfla fa' }] - }); -}); - -console.error('completed %d docs in %d seconds (%d dps)', numdocs, totaltime, numdocs / totaltime); \ No newline at end of file diff --git a/benchmarks/mapOfSubdocs.js b/benchmarks/mapOfSubdocs.js index 9fc6e40191..dc45001744 100644 --- a/benchmarks/mapOfSubdocs.js +++ b/benchmarks/mapOfSubdocs.js @@ -8,13 +8,12 @@ run().catch(err => { }); async function run() { - await mongoose.connect('mongodb://127.0.0.1:27017/mongoose_test', { + await mongoose.connect('mongodb://127.0.0.1:27017/mongoose_benchmark', { serverSelectionTimeoutMS: 5000 }); const minisMap = new mongoose.Schema( { - //? Mini reference mini: { type: Map, of: new mongoose.Schema({ @@ -25,8 +24,6 @@ async function run() { }), }, }, - //? Automatic creation of timestamps for creation and updating. - //? This will be created on the background by the package { timestamps: true } ); const MinisMap = mongoose.model('MinisMap', minisMap); diff --git a/benchmarks/mem.js b/benchmarks/mem.js deleted file mode 100644 index c73acac33e..0000000000 --- a/benchmarks/mem.js +++ /dev/null @@ -1,165 +0,0 @@ -'use strict'; - -const mongoose = require('../'); - -const Schema = mongoose.Schema; - -mongoose.connect('mongodb://127.0.0.1/mongoose-bench'); - -const DocSchema = new Schema({ - title: String -}); - -const AllSchema = new Schema({ - string: { type: String, required: true }, - number: { type: Number, min: 10 }, - date: Date, - bool: Boolean, - buffer: Buffer, - objectid: Schema.ObjectId, - array: Array, - strings: [String], - numbers: [Number], - dates: [Date], - bools: [Boolean], - buffers: [Buffer], - objectids: [Schema.ObjectId], - docs: { - type: [DocSchema], validate: function() { - return true; - } - }, - s: { nest: String } -}); - -const A = mongoose.model('A', AllSchema); - -const methods = []; -methods.push(function(a, cb) { - A.findOne({ _id: a._id }, cb); -}); // 2 MB -methods.push(function(a, cb) { - A.find({ _id: a._id, bool: a.bool }, cb); -}); // 3.8 MB -methods.push(function(a, cb) { - A.findById(a._id, cb); -}); // 4.6 MB -methods.push(function(a, cb) { - A.where('number', a.number).limit(10).exec(cb); -}); // 4.8 MB -methods.push(function(a, cb) { - A.where('date', a.date).select('string').limit(10).exec(cb); -}); // 3.5 mb -methods.push(function(a, cb) { - A.where('date', a.date).select('string bool').limit(10).exec(cb); -}); // 3.5 MB -methods.push(function(a, cb) { - A.where('date', a.date).where('array').in(3).limit(10).exec(cb); -}); // 1.82 MB -methods.push(function(a, cb) { - A.updateOne({ _id: a._id }, { $addToset: { array: 'heeeeello' } }, cb); -}); // 3.32 MB -methods.push(function(a, cb) { - A.deleteOne({ _id: a._id }, cb); -}); // 3.32 MB -methods.push(function(a, cb) { - A.find().where('objectids').exists().select('dates').limit(10).exec(cb); -}); // 3.32 MB -methods.push(function(a, cb) { - A.count({ strings: a.strings[2], number: a.number }, cb); -}); // 3.32 MB -methods.push(function(a, cb) { - a.string = 'asdfaf'; - a.number = 38383838; - a.date = new Date; - a.bool = false; - a.array.push(3); - a.dates.push(new Date); - // a.bools.push([true, false]); - a.docs.addToSet({ title: 'woot' }); - a.strings.remove('three'); - a.numbers.pull(72); - a.objectids.$pop(); - a.docs.pull.apply(a.docs, a.docs); - a.s.nest = 'aooooooga'; - - if (i % 2) { - a.toObject({ depopulate: true }); - } else { - if (a._delta) { - a._delta(); - } else { - a.$__delta(); - } - } - - cb(); -}); - -const started = process.memoryUsage(); -const start = new Date; -const total = 10000; -let i = total; - -function done() { - const time = (new Date - start); - const used = process.memoryUsage(); - - const res = {}; - res.rss = used.rss - started.rss; - res.heapTotal = used.heapTotal - started.heapTotal; - res.heapUsed = used.heapUsed - started.heapUsed; - - console.error('took %d ms for %d docs (%d dps)', time, total, total / (time / 1000), 'change: ', res); - - mongoose.connection.db.dropDatabase(function() { - mongoose.connection.close(); - }); -} - -function cycle() { - if (i-- === 0) { - return done(); - } - let a = new A({ - string: 'hello world', - number: 444848484, - date: new Date, - bool: true, - buffer: Buffer.alloc(0), - objectid: new mongoose.Types.ObjectId(), - array: [4, {}, [], 'asdfa'], - strings: ['one', 'two', 'three', 'four'], - numbers: [72, 6493, 83984643, 348282.55], - dates: [new Date, new Date, new Date], - bools: [true, false, false, true, true], - buffers: [Buffer.from([33]), Buffer.from([12])], - objectids: [new mongoose.Types.ObjectId], - docs: [{ title: 'yo' }, { title: 'nowafasdi0fas asjkdfla fa' }] - }); - - a.save(function() { - methods[Math.random() * methods.length | 0](a, function() { - a = null; - process.nextTick(cycle); - }); - }); - - /* if (i%2) - a.toObject({ depopulate: true }); - else - a._delta(); - - if (!(i%50)) { - var u = process.memoryUsage(); - console.error('rss: %d, vsize: %d, heapTotal: %d, heapUsed: %d', - u.rss, u.vsize, u.heapTotal, u.heapUsed); - } */ -} - -mongoose.connection.on('open', function() { - mongoose.connection.db.dropDatabase(function() { - cycle(); - // --trace-opt --trace-deopt --trace-bailout - }); -}); diff --git a/benchmarks/populate.js b/benchmarks/populate.js deleted file mode 100644 index 2be29e72e0..0000000000 --- a/benchmarks/populate.js +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; -const mongoose = require('../'); -const Schema = mongoose.Schema; -const docs = process.argv[2] ? process.argv[2] | 0 : 100; - -const A = mongoose.model('A', Schema({ name: 'string' })); - -const nested = Schema({ - a: { type: Schema.ObjectId, ref: 'A' } -}); - -const B = mongoose.model('B', Schema({ - as: [{ type: Schema.ObjectId, ref: 'A' }], - a: { type: Schema.ObjectId, ref: 'A' }, - nested: [nested] -})); - -let start; -let count = 0; - -mongoose.connect('mongodb://127.0.0.1/mongoose-bench', function(err) { - if (err) { - return done(err); - } - - A.create({ name: 'wooooooooooooooooooooooooooooooooooooooooot' }, function(err, a) { - if (err) { - return done(err); - } - - let pending = docs; - for (let i = 0; i < pending; ++i) { - new B({ - as: [a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a], - a: a, - nested: [{ a: a }, { a: a }, { a: a }, { a: a }, { a: a }, { a: a }] - }).save(function(err) { - if (err) { - return done(err); - } - --pending; - if (pending === 0) { - // console.log('inserted %d docs. beginning test ...', docs); - start = Date.now(); - test(); - } - }); - } - }); -}); - -function test() { - let pending = 2; - - B.find().populate('as').populate('a').populate('nested.a').exec(handle); - B.findOne().populate('as').populate('a').populate('nested.a').exec(handle); - - function handle(err) { - if (err) { - throw err; - } - count++; - - if (Date.now() - start > 1000 * 20) { - return done(); - } - - if (--pending === 0) { - return test(); - } - } -} - - -function done(err) { - if (err) { - console.error(err.stack); - } - - mongoose.connection.db.dropDatabase(function() { - mongoose.disconnect(); - console.log('%d completed queries on mongoose version %s', count, mongoose.version); - }); -} diff --git a/benchmarks/recursiveToObject.js b/benchmarks/recursiveToObject.js new file mode 100644 index 0000000000..2760df44da --- /dev/null +++ b/benchmarks/recursiveToObject.js @@ -0,0 +1,60 @@ +'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', { + serverSelectionTimeoutMS: 5000 + }); + + const ChildSchema = new mongoose.Schema({ name: String, parentId: 'ObjectId' }); + ChildSchema.virtual('answer').get(function() { return 42; }); + const ChildModel = mongoose.model('Child', ChildSchema); + + const ParentSchema = new mongoose.Schema({ + name: String + }); + ParentSchema.virtual('child1', { ref: 'Child', localField: '_id', foreignField: 'parentId' }); + ParentSchema.virtual('child2', { ref: 'Child', localField: '_id', foreignField: 'parentId' }); + ParentSchema.virtual('child3', { ref: 'Child', localField: '_id', foreignField: 'parentId' }); + ParentSchema.virtual('child4', { ref: 'Child', localField: '_id', foreignField: 'parentId' }); + const ParentModel = mongoose.model('Parent', ParentSchema); + + if (!process.env.MONGOOSE_BENCHMARK_SKIP_SETUP) { + await ParentModel.deleteMany({}); + await ChildModel.deleteMany({}); + + const numDocs = 200; + const parents = []; + for (let i = 0; i < numDocs; ++i) { + const parent = await ParentModel.create({ name: 'test parent ' + i }); + const children = []; + console.log(`${i} / ${numDocs}`); + for (let j = 0; j < numDocs; ++j) { + children.push({ name: 'test child ' + i + '_' + j, parentId: parent._id }); + } + await ChildModel.create(children); + parents.push(parent); + } + } + + const docs = await ParentModel.find().populate(['child1', 'child2', 'child3', 'child4']); + for (const doc of docs) { + doc.name = 'test parent'; + } + const loopStart = Date.now(); + + docs.forEach(doc => doc.toObject({ virtuals: true })); + + const results = { + 'Total toObject time ms': Date.now() - loopStart + }; + + console.log(JSON.stringify(results, null, ' ')); + process.exit(0); +} \ No newline at end of file diff --git a/benchmarks/validate.js b/benchmarks/validate.js deleted file mode 100644 index 97e4105199..0000000000 --- a/benchmarks/validate.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -const mongoose = require('../../mongoose'); -const Benchmark = require('benchmark'); - -const Schema = mongoose.Schema; -const breakfastSchema = new Schema({ - eggs: { - type: Number, - min: [6, 'Too few eggs'], - max: 12 - }, - bacon: { - type: Number, - required: [true, 'Why no bacon?'] - }, - drink: { - type: String, - enum: ['Coffee', 'Tea'], - required: function() { - return this.bacon > 3; - } - } -}); -const Breakfast = mongoose.model('Breakfast', breakfastSchema); - -const badBreakfast = new Breakfast({ - eggs: 2, - bacon: 0, - drink: 'Milk' -}); - -const goodBreakfast = new Breakfast({ - eggs: 6, - bacon: 1, - drink: 'Tea' -}); - -const suite = new Benchmark.Suite(); -suite - .add('invalid async', { - defer: true, - fn: function(deferred) { - // avoid test inlining - suite.name; - badBreakfast.validate().catch(() => deferred.resolve()); - } - }) - .add('valid async', { - defer: true, - fn: function(deferred) { - // avoid test inlining - suite.name; - goodBreakfast.validate().then(() => deferred.resolve()); - } - }) - .add('invalid sync', function() { - badBreakfast.validateSync(); - }) - .add('valid sync', function() { - goodBreakfast.validateSync(); - }) - .on('cycle', function(evt) { - if (process.env.MONGOOSE_DEV || process.env.PULL_REQUEST) { - console.log(String(evt.target)); - } - }) - .run(); \ No newline at end of file From 98f20f35e1d390ffb6cd9612ec14530d8fd2f725 Mon Sep 17 00:00:00 2001 From: Valeri Karpov <val@karpov.io> Date: Fri, 31 May 2024 10:26:22 -0400 Subject: [PATCH 5/7] chore: remove unused dependency benchmark --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 975d46d682..a07cf63130 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "assert-browserify": "2.0.0", "axios": "1.1.3", "babel-loader": "8.2.5", - "benchmark": "2.1.4", "broken-link-checker": "^0.7.8", "buffer": "^5.6.0", "cheerio": "1.0.0-rc.12", From 75c6f8887901be602ca2291ef3d2ffd57b076507 Mon Sep 17 00:00:00 2001 From: Valeri Karpov <val@karpov.io> Date: Fri, 31 May 2024 10:43:19 -0400 Subject: [PATCH 6/7] perf: memoize default toObject options on a per-schema basis re: #14394 --- lib/document.js | 21 ++------------------- lib/schema.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/document.js b/lib/document.js index bdb6e2e57d..8236fa820a 100644 --- a/lib/document.js +++ b/lib/document.js @@ -22,7 +22,6 @@ const clone = require('./helpers/clone'); const compile = require('./helpers/document/compile').compile; const defineKey = require('./helpers/document/compile').defineKey; const flatten = require('./helpers/common').flatten; -const get = require('./helpers/get'); const getEmbeddedDiscriminatorPath = require('./helpers/document/getEmbeddedDiscriminatorPath'); const getKeysInSchemaOrder = require('./helpers/schema/getKeysInSchemaOrder'); const getSubdocumentStrictValue = require('./helpers/schema/getSubdocumentStrictValue'); @@ -3798,15 +3797,7 @@ Document.prototype.$__handleReject = function handleReject(err) { */ Document.prototype.$toObject = function(options, json) { - const path = json ? 'toJSON' : 'toObject'; - const baseOptions = this.constructor && - this.constructor.base && - this.constructor.base.options && - get(this.constructor.base.options, path) || {}; - const schemaOptions = this.$__schema && this.$__schema.options || {}; - // merge base default options with Schema's set default options if available. - // `clone` is necessary here because `utils.options` directly modifies the second input. - const defaultOptions = Object.assign({}, baseOptions, schemaOptions[path]); + const defaultOptions = this.$__schema._getDefaultToObjectOptions(); // If options do not exist or is not an object, set it to empty object options = utils.isPOJO(options) ? { ...options } : {}; @@ -3815,10 +3806,8 @@ Document.prototype.$toObject = function(options, json) { let _minimize; if (options._calledWithOptions.minimize != null) { _minimize = options.minimize; - } else if (defaultOptions.minimize != null) { - _minimize = defaultOptions.minimize; } else { - _minimize = schemaOptions.minimize; + _minimize = defaultOptions.minimize; } options.minimize = _minimize; @@ -3842,14 +3831,8 @@ Document.prototype.$toObject = function(options, json) { } options._isNested = true; options.json = json; - options.minimize = _minimize; - options._parentOptions = options; - options._skipSingleNestedGetters = false; - // remember the root transform function - // to save it from being overwritten by sub-transform functions - // const originalTransform = options.transform; let ret = clone(this._doc, options) || {}; diff --git a/lib/schema.js b/lib/schema.js index 4dfefccf54..96de706ed2 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -128,6 +128,7 @@ function Schema(obj, options) { // For internal debugging. Do not use this to try to save a schema in MDB. this.$id = ++id; this.mapPaths = []; + this._defaultToObjectOptions = null; this.s = { hooks: new Kareem() @@ -2597,6 +2598,33 @@ Schema.prototype.loadClass = function(model, virtualsOnly) { return this; }; +/** + * Returns default `toObject` / `toJSON` options for this schema, + * combining the associated + * + * @param {Boolean} json + * @returns object + */ + +Schema.prototype._getDefaultToObjectOptions = function _getDefaultToObjectOptions(json) { + const path = json ? 'toJSON' : 'toObject'; + + if (this._defaultToObjectOptions && this._defaultToObjectOptions[path]) { + return this._defaultToObjectOptions[path]; + } + + const baseOptions = this.base && this.base.options && this.base.options[path]; + const schemaOptions = this.options && this.options[path]; + const defaultOptions = Object.assign( + {}, + baseOptions, + schemaOptions + ); + this._defaultToObjectOptions = this._defaultToObjectOptions || {}; + this._defaultToObjectOptions[path] = defaultOptions; + return defaultOptions; +}; + /*! * ignore */ From c26fda01a8e4eccc4f0f362d7298e22b220bc155 Mon Sep 17 00:00:00 2001 From: Valeri Karpov <val@karpov.io> Date: Fri, 31 May 2024 11:02:27 -0400 Subject: [PATCH 7/7] Revert "perf: memoize default toObject options on a per-schema basis re: #14394" This reverts commit 75c6f8887901be602ca2291ef3d2ffd57b076507. --- lib/document.js | 21 +++++++++++++++++++-- lib/schema.js | 28 ---------------------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/lib/document.js b/lib/document.js index 8236fa820a..bdb6e2e57d 100644 --- a/lib/document.js +++ b/lib/document.js @@ -22,6 +22,7 @@ const clone = require('./helpers/clone'); const compile = require('./helpers/document/compile').compile; const defineKey = require('./helpers/document/compile').defineKey; const flatten = require('./helpers/common').flatten; +const get = require('./helpers/get'); const getEmbeddedDiscriminatorPath = require('./helpers/document/getEmbeddedDiscriminatorPath'); const getKeysInSchemaOrder = require('./helpers/schema/getKeysInSchemaOrder'); const getSubdocumentStrictValue = require('./helpers/schema/getSubdocumentStrictValue'); @@ -3797,7 +3798,15 @@ Document.prototype.$__handleReject = function handleReject(err) { */ Document.prototype.$toObject = function(options, json) { - const defaultOptions = this.$__schema._getDefaultToObjectOptions(); + const path = json ? 'toJSON' : 'toObject'; + const baseOptions = this.constructor && + this.constructor.base && + this.constructor.base.options && + get(this.constructor.base.options, path) || {}; + const schemaOptions = this.$__schema && this.$__schema.options || {}; + // merge base default options with Schema's set default options if available. + // `clone` is necessary here because `utils.options` directly modifies the second input. + const defaultOptions = Object.assign({}, baseOptions, schemaOptions[path]); // If options do not exist or is not an object, set it to empty object options = utils.isPOJO(options) ? { ...options } : {}; @@ -3806,8 +3815,10 @@ Document.prototype.$toObject = function(options, json) { let _minimize; if (options._calledWithOptions.minimize != null) { _minimize = options.minimize; - } else { + } else if (defaultOptions.minimize != null) { _minimize = defaultOptions.minimize; + } else { + _minimize = schemaOptions.minimize; } options.minimize = _minimize; @@ -3831,8 +3842,14 @@ Document.prototype.$toObject = function(options, json) { } options._isNested = true; options.json = json; + options.minimize = _minimize; + options._parentOptions = options; + options._skipSingleNestedGetters = false; + // remember the root transform function + // to save it from being overwritten by sub-transform functions + // const originalTransform = options.transform; let ret = clone(this._doc, options) || {}; diff --git a/lib/schema.js b/lib/schema.js index 96de706ed2..4dfefccf54 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -128,7 +128,6 @@ function Schema(obj, options) { // For internal debugging. Do not use this to try to save a schema in MDB. this.$id = ++id; this.mapPaths = []; - this._defaultToObjectOptions = null; this.s = { hooks: new Kareem() @@ -2598,33 +2597,6 @@ Schema.prototype.loadClass = function(model, virtualsOnly) { return this; }; -/** - * Returns default `toObject` / `toJSON` options for this schema, - * combining the associated - * - * @param {Boolean} json - * @returns object - */ - -Schema.prototype._getDefaultToObjectOptions = function _getDefaultToObjectOptions(json) { - const path = json ? 'toJSON' : 'toObject'; - - if (this._defaultToObjectOptions && this._defaultToObjectOptions[path]) { - return this._defaultToObjectOptions[path]; - } - - const baseOptions = this.base && this.base.options && this.base.options[path]; - const schemaOptions = this.options && this.options[path]; - const defaultOptions = Object.assign( - {}, - baseOptions, - schemaOptions - ); - this._defaultToObjectOptions = this._defaultToObjectOptions || {}; - this._defaultToObjectOptions[path] = defaultOptions; - return defaultOptions; -}; - /*! * ignore */