Uploaded image for project: 'Ruby Driver'
  1. Ruby Driver
  2. RUBY-939

Socket#eof? doesn't exist

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 2.0.5
    • Affects Version/s: 2.0.4
    • Component/s: Connections
    • Labels:
      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

            Assignee:
            durran.jordan@mongodb.com Durran Jordan
            Reporter:
            cheald Chris Heald
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: