-
Type: Bug
-
Resolution: Done
-
Priority: Major - P3
-
Affects Version/s: 2.0.4
-
Component/s: Connections
-
None
-
Fully Compatible
https://github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/socket.rb#L60
This results in massive performance issues in some VMs, because socket#alive? never returns true and an exception is thrown for every single invocation of this method. The performance penalty is extremely pronounced under JRuby, where exceptions have a relatively high overhead cost.
The use of `x rescue y` is an antipattern (https://github.com/bbatsov/ruby-style-guide#exceptions) that should be avoided specifically because it leads to issues like this, where legitimate bugs are hidden. Specific exceptions (IOError in this case) should be caught instead.
Benchmarking the change:
require 'bundler/setup' require 'mongo' require 'benchmark' Mongo::Logger.logger.level = Logger::FATAL def iterate_oplog client = Mongo::Client.new ["localhost:27017"], database: "local", min_pool_size: 2, max_pool_size: 2 seekts = client["oplog.rs"].find().sort({:$natural => -1}).skip(50000).first["ts"] finder = {ts: {:$gt => seekts}} cursor = client["oplog.rs"].find(finder).tap do |c| c.send(:flags).replace [:no_cursor_timeout, :oplog_replay, :slave_ok] end cursor.each do |op| db, coll = op["ns"].split(".", 2) id = (op["o"] && op["o"]["_id"]) || (op["pk"] && op["pk"].values.first) next unless id client.with(database: db)[coll].find({_id: id}).first end end Benchmark.bmbm do |x| x.report("iterate oplog") { iterate_oplog } end
BEFORE - JRuby 1.7.19 Rehearsal ------------------------------------------------- iterate oplog 60.750000 2.630000 63.380000 ( 36.072000) --------------------------------------- total: 63.380000sec user system total real iterate oplog 21.130000 1.580000 22.710000 ( 15.898000) AFTER - JRuby 1.7.19 Rehearsal ------------------------------------------------- iterate oplog 35.730000 2.210000 37.940000 ( 24.393000) --------------------------------------- total: 37.940000sec user system total real iterate oplog 13.080000 1.420000 14.500000 ( 12.154000)
JRuby 1.7.19: 21 sec -> 13 sec (-38% runtime)
My fix is here:
https://github.com/cheald/mongo-ruby-driver/commit/421e1c1f8ef12c804dd3165fe27772acf4c39617