Hello @Ilya_Starovoytov, thank you for sharing your results and some code to reproduce them. This is very helpful.
I’ve taken the code you provided and put it in a single script—I believe it all does the same thing yours does, and I do see a performance regression going from 7.5.4 to 8.1.4. However, in my case, it’s only about 6x slower, rather than ~100x slower.
This is still significant, and we intend to investigate it, but I want to make sure that I’m investigating the same behavior you’re seeing. Can you take the script I’m using (copied below) and confirm the same performance you reported?
require 'mongoid'
require 'factory_bot'
require 'rspec/autorun'
Mongoid.connect_to 'mongoid-5740'
Mongoid.purge!
class First
include Mongoid::Document
include Mongoid::Timestamps::Short
field :name, type: String
has_many :seconds, dependent: :destroy
has_many :thirds, dependent: :destroy
validates_uniqueness_of :name
validates_presence_of :name
end
class Second
include Mongoid::Document
include Mongoid::Timestamps::Short
field :name, type: String
belongs_to :first
has_and_belongs_to_many :thirds
end
class Third
include Mongoid::Document
include Mongoid::Timestamps::Short
field :name, type: String
validates_presence_of :name
validates_format_of :name, without: /\/|\\|\&|\?|\s/
has_and_belongs_to_many :seconds
belongs_to :first
end
FactoryBot.define do
factory :first do
sequence(:name){ |i| "First_name_#{i}" }
end
end
FactoryBot.define do
factory :second do
sequence(:name){ |i| "Second_name_#{i}" }
end
end
FactoryBot.define do
factory :third do
sequence(:name){ |i| "Third_name_#{i}" }
end
end
RSpec.describe 'insert performance' do
include FactoryBot::Syntax::Methods
let(:first) { create(:first) }
let(:second_1) { create(:second, first: first) }
let(:second_2) { create(:second, first: first) }
let(:thirds_1000) { create_list(:third, 1000, first: first, seconds: [second_1, second_2]) }
it 'checks 1000 thirds insertion' do
start_time = Time.now.utc
thirds_1000
puts "[#{Mongoid::VERSION}]: #{Time.now.utc - start_time} seconds"
end
end
When I run this against 7.5.4, 8.0.7, 8.1.4, and the master branch (9.0.0-alpha), I get the following timings (on my M1 Macbook, against MongoDB 7.0.5 running locally in a sharded configuration):
[7.5.4]: 33.691952 seconds
[8.0.7]: 186.871009 seconds
[8.1.4]: 186.438292 seconds
[9.0.0.alpha]: 173.630884 seconds
The performance regression I’m seeing here seems to be related to belongs_to associations enforcing validations all the way up the association chain, on save. When I set Mongoid.belongs_to_required_by_default = false and re-run the test, I get the following timings:
[8.0.7]: 31.389694 seconds
[8.1.4]: 29.274998 seconds
[9.0.0.alpha]: 35.607121 seconds
Which, as you can see, puts the results back into the same ballpark as 7.5.4. We are currently tracking this particular regression in the following tickets:
I’m hoping that you’re encountering this same regression, rather than something new, but please let me know what you see when you run this script. Thank you again!