From 3362fb5be62b1e7efbb44538d1c34a0d57420a7c Mon Sep 17 00:00:00 2001 From: Kyle Banker Date: Thu, 12 Nov 2009 14:48:49 -0500 Subject: [PATCH] Simplified BSON serialization calls for performance. --- lib/mongo.rb | 7 +++++++ lib/mongo/collection.rb | 8 ++++---- lib/mongo/cursor.rb | 4 ++-- lib/mongo/db.rb | 12 ++++++++++-- lib/mongo/util/bson.rb | 12 ++++++++++++ lib/mongo/util/byte_buffer.rb | 6 ++++-- 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/lib/mongo.rb b/lib/mongo.rb index bf4f989..365de1f 100644 --- a/lib/mongo.rb +++ b/lib/mongo.rb @@ -18,6 +18,13 @@ require 'mongo/cursor' require 'mongo/collection' require 'mongo/admin' +begin + require 'mongo_ext/cbson' + BSON_SERIALIZER = CBson + rescue LoadError + BSON_SERIALIZER = BSON +end + module Mongo ASCENDING = 1 DESCENDING = -1 diff --git a/lib/mongo/collection.rb b/lib/mongo/collection.rb index 7d04b7f..9bfdfe8 100644 --- a/lib/mongo/collection.rb +++ b/lib/mongo/collection.rb @@ -221,7 +221,7 @@ module Mongo message.put_int(0) BSON.serialize_cstr(message, "#{@db.name}.#{@name}") message.put_int(0) - message.put_array(BSON.new.serialize(selector, false).to_a) + message.put_array(BSON_SERIALIZER.serialize(selector, false).unpack("C*")) @db.send_message_with_operation(Mongo::Constants::OP_DELETE, message, "db.#{@db.name}.remove(#{selector.inspect})") end @@ -258,8 +258,8 @@ module Mongo update_options += 1 if options[:upsert] update_options += 2 if options[:multi] message.put_int(update_options) - message.put_array(BSON.new.serialize(selector, false).to_a) - message.put_array(BSON.new.serialize(document, false).to_a) + message.put_array(BSON_SERIALIZER.serialize(selector, false).unpack("C*")) + message.put_array(BSON_SERIALIZER.serialize(document, false).unpack("C*")) if options[:safe] @db.send_message_with_safe_check(Mongo::Constants::OP_UPDATE, message, "db.#{@name}.update(#{selector.inspect}, #{document.inspect})") @@ -486,7 +486,7 @@ EOS message = ByteBuffer.new message.put_int(0) BSON.serialize_cstr(message, "#{@db.name}.#{collection_name}") - documents.each { |doc| message.put_array(BSON.new.serialize(doc, check_keys).to_a) } + documents.each { |doc| message.put_array(BSON_SERIALIZER.serialize(doc, check_keys).unpack("C*")) } if safe @db.send_message_with_safe_check(Mongo::Constants::OP_INSERT, message, "db.#{collection_name}.insert(#{documents.inspect})") diff --git a/lib/mongo/cursor.rb b/lib/mongo/cursor.rb index 7e49330..86fb64f 100644 --- a/lib/mongo/cursor.rb +++ b/lib/mongo/cursor.rb @@ -322,8 +322,8 @@ module Mongo if query_contains_special_fields? selector = selector_with_special_query_fields end - message.put_array(BSON.new.serialize(selector).to_a) - message.put_array(BSON.new.serialize(@fields).to_a) if @fields + message.put_array(BSON_SERIALIZER.serialize(selector, false).unpack("C*")) + message.put_array(BSON_SERIALIZER.serialize(@fields, false).unpack("C*")) if @fields message end diff --git a/lib/mongo/db.rb b/lib/mongo/db.rb index afdafd5..e6b7521 100644 --- a/lib/mongo/db.rb +++ b/lib/mongo/db.rb @@ -450,6 +450,14 @@ module Mongo end end + def send_message_with_operation_raw(operation, message, log_message=nil) + message_with_headers = add_message_headers_raw(operation, message) + @logger.debug(" MONGODB #{log_message || message}") if @logger + @semaphore.synchronize do + send_message_on_socket(message_with_headers) + end + end + # Sends a message to the database, waits for a response, and raises # and exception if the operation has failed. def send_message_with_safe_check(operation, message, log_message=nil) @@ -641,7 +649,7 @@ module Mongo BSON.serialize_cstr(message, "#{@name}.$cmd") message.put_int(0) message.put_int(-1) - message.put_array(BSON.new.serialize({:getlasterror => 1}).to_a) + message.put_array(BSON_SERIALIZER.serialize({:getlasterror => 1}, false).unpack("C*")) add_message_headers(Mongo::Constants::OP_QUERY, message) end @@ -655,7 +663,7 @@ module Mongo BSON.serialize_cstr(message, "#{@name}.$cmd") message.put_int(0) message.put_int(-1) - message.put_array(BSON.new.serialize({:reseterror => 1}).to_a) + message.put_array(BSON_SERIALIZER.serialize({:reseterror => 1}, false).unpack("C*")) add_message_headers(Mongo::Constants::OP_QUERY, message) end diff --git a/lib/mongo/util/bson.rb b/lib/mongo/util/bson.rb index 377951e..d67d950 100644 --- a/lib/mongo/util/bson.rb +++ b/lib/mongo/util/bson.rb @@ -71,6 +71,12 @@ class BSON @buf.to_a end + # Serializes an object. + # Implemented to ensure an API compatible with BSON extension. + def self.serialize(obj, check_keys) + new.serialize(obj, check_keys) + end + begin require 'mongo_ext/cbson' def serialize(obj, check_keys=false) @@ -99,6 +105,12 @@ class BSON end end + # Returns the array stored in the buffer. + # Implemented to ensure an API compatible with BSON extension. + def unpack(arg) + @buf.to_a + end + def serialize_key_value(k, v, check_keys) k = k.to_s if check_keys diff --git a/lib/mongo/util/byte_buffer.rb b/lib/mongo/util/byte_buffer.rb index 52bb89a..707702a 100644 --- a/lib/mongo/util/byte_buffer.rb +++ b/lib/mongo/util/byte_buffer.rb @@ -20,9 +20,11 @@ class ByteBuffer attr_reader :order def initialize(initial_data=[]) - @buf = initial_data + @buf = initial_data @cursor = 0 - self.order = :little_endian + @order = :little_endian + @int_pack_order = 'V' + @double_pack_order = 'E' end # +endianness+ should be :little_endian or :big_endian. Default is :little_endian