<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -38,6 +38,8 @@
 
 #include &lt;assert.h&gt;
 #include &lt;math.h&gt;
+#include &lt;unistd.h&gt;
+#include &lt;time.h&gt;
 
 #define INITIAL_BUFFER_SIZE 256
 
@@ -49,6 +51,7 @@ static VALUE Code;
 static VALUE RegexpOfHolding;
 static VALUE OrderedHash;
 static VALUE InvalidName;
+static VALUE DigestMD5;
 
 #if HAVE_RUBY_ENCODING_H
 #include &quot;ruby/encoding.h&quot;
@@ -737,8 +740,58 @@ static VALUE method_deserialize(VALUE self, VALUE bson) {
     return elements_to_hash(buffer, remaining);
 }
 
+
+static VALUE fast_pack(VALUE self)
+{
+    VALUE res;
+    long i;
+    char c;
+
+    res = rb_str_buf_new(0);
+
+    for (i = 0; i &lt; RARRAY(self)-&gt;len; i++) {
+        c = FIX2LONG(RARRAY(self)-&gt;ptr[i]);
+        rb_str_buf_cat(res, &amp;c, sizeof(char));
+    }
+
+    return res;
+}
+
+
+static VALUE objectid_generate(VALUE self)
+{
+    VALUE ary, digest, hostname;
+    unsigned char *string;
+    unsigned long t, pid, inc;
+    int i;
+
+    string = ALLOC_N(unsigned char, 13);
+    hostname = rb_str_buf_new(64);
+
+    t = htonl(time(NULL));
+    MEMCPY(string, &amp;t, char, 4);
+
+    gethostname(RSTRING(hostname)-&gt;ptr, 64);
+    RSTRING(hostname)-&gt;len = strlen(RSTRING(hostname)-&gt;ptr);
+    digest = rb_funcall(DigestMD5, rb_intern(&quot;hexdigest&quot;), 1, hostname);
+    MEMCPY(string+4, RSTRING(digest)-&gt;ptr, unsigned char, 3);
+
+    pid = htonl(getpid());
+    MEMCPY(string+7, &amp;pid, char, 2);
+
+    inc = htonl(FIX2ULONG(rb_funcall(self, rb_intern(&quot;get_inc&quot;), 0)));
+    MEMCPY(string+9, ((unsigned char*)&amp;inc + 1), unsigned char, 3);
+
+    ary = rb_ary_new2(12);
+    for(i = 0; i &lt; 12; i++)
+        rb_ary_store(ary, i, INT2FIX((unsigned int)string[i]));
+    free(string);
+    return ary;
+}
+
+
 void Init_cbson() {
-    VALUE mongo, CBson;
+    VALUE mongo, CBson, Digest;
     Time = rb_const_get(rb_cObject, rb_intern(&quot;Time&quot;));
 
     mongo = rb_const_get(rb_cObject, rb_intern(&quot;Mongo&quot;));
@@ -760,4 +813,12 @@ void Init_cbson() {
     CBson = rb_define_module(&quot;CBson&quot;);
     rb_define_module_function(CBson, &quot;serialize&quot;, method_serialize, 2);
     rb_define_module_function(CBson, &quot;deserialize&quot;, method_deserialize, 1);
+
+    rb_require(&quot;digest/md5&quot;);
+    Digest = rb_const_get(rb_cObject, rb_intern(&quot;Digest&quot;));
+    DigestMD5 = rb_const_get(Digest, rb_intern(&quot;MD5&quot;));
+
+    rb_define_method(ObjectID, &quot;generate&quot;, objectid_generate, 0);
+
+    rb_define_method(rb_cArray, &quot;fast_pack&quot;, fast_pack, 0);
 }</diff>
      <filename>ext/cbson/cbson.c</filename>
    </modified>
    <modified>
      <diff>@@ -120,23 +120,27 @@ module Mongo
 
     private
 
-    def generate
-      oid = ''
+    begin
+      require 'mongo_ext/cbson'
+    rescue LoadError
+      def generate
+        oid = ''
 
-      # 4 bytes current time
-      time = Time.new.to_i
-      oid += [time].pack(&quot;N&quot;)
+        # 4 bytes current time
+        time = Time.new.to_i
+        oid += [time].pack(&quot;N&quot;)
 
-      # 3 bytes machine
-      oid += Digest::MD5.digest(Socket.gethostname)[0, 3]
+        # 3 bytes machine
+        oid += Digest::MD5.digest(Socket.gethostname)[0, 3]
 
-      # 2 bytes pid
-      oid += [Process.pid % 0xFFFF].pack(&quot;n&quot;)
+        # 2 bytes pid
+        oid += [Process.pid % 0xFFFF].pack(&quot;n&quot;)
 
-      # 3 bytes inc
-      oid += [get_inc].pack(&quot;N&quot;)[1, 3]
+        # 3 bytes inc
+        oid += [get_inc].pack(&quot;N&quot;)[1, 3]
 
-      oid.unpack(&quot;C12&quot;)
+        oid.unpack(&quot;C12&quot;)
+      end
     end
 
     def get_inc</diff>
      <filename>lib/mongo/types/objectid.rb</filename>
    </modified>
    <modified>
      <diff>@@ -159,7 +159,9 @@ class ByteBuffer
   end
 
   def to_s
-    if @buf.respond_to? &quot;pack&quot;
+    if @buf.respond_to? :fast_pack
+      @buf.fast_pack
+    elsif @buf.respond_to? &quot;pack&quot;
       @buf.pack(&quot;C*&quot;)
     else
       @buf</diff>
      <filename>lib/mongo/util/byte_buffer.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>5a81cb70eee81e9387ee125c0ea8cb5bb1e6c329</id>
    </parent>
  </parents>
  <author>
    <name>Sean Cribbs</name>
    <email>seancribbs@gmail.com</email>
  </author>
  <url>http://github.com/mongodb/mongo-ruby-driver/commit/cb4d94f541371f3d32a25fee3ba820e9d0d9dbe1</url>
  <id>cb4d94f541371f3d32a25fee3ba820e9d0d9dbe1</id>
  <committed-date>2009-10-29T08:44:07-07:00</committed-date>
  <authored-date>2009-10-29T08:44:07-07:00</authored-date>
  <message>Optimize ByteBuffer#to_s and Mongo::ObjectID#generate via C extensions.</message>
  <tree>a525158c5c424a3e8b702b0974c21329b09a2183</tree>
  <committer>
    <name>Sean Cribbs</name>
    <email>seancribbs@gmail.com</email>
  </committer>
</commit>
