Anybody can explain it clearer?
Ada yang bisa menjelaskan dg lebih gamblang?

[EMAIL PROTECTED]:~/Documents/spikes$ cat bm.rb

require 'benchmark'
include Benchmark

string1 = 'string %s'
string2 = 'string'
bm(6) do |x|
        x.report('%') { 10_000_000.times { string1 % 'persen' } }
        x.report('+') { 10_000_000.times { string2 + ' tambah' } }
end


[EMAIL PROTECTED]:~/Documents/spikes$ ruby bm.rb

             user     system      total        real
%      21.300000   1.920000  23.220000 ( 23.278688)
+      12.750000   1.920000  14.670000 ( 14.683736)


Dugaan sementara ariekeren ya itu + cuma concat, sedang % bisa replace 
jadi memang kelebihannya itu juga dibayar dengan performa, karena 
sebetulnya sebelum tembak dengan sepuluh juta itu ariekeren pakai 
sepuluh ribu hasil benchmarknya gini (semua sampai totalnya sama, beda 
di realnya):

             user     system      total        real
%       0.020000   0.000000   0.020000 (  0.024216)
+       0.020000   0.000000   0.020000 (  0.014881)


Silakan buat teman-teman yang mungkin ada analisis lebih lanjut?


Berikut ini source code di source code ruby (ya, pakai C)
File: /home/arie/Documents/sources/ruby/string.c


/*
  *  call-seq:
  *     str + other_str   => new_str
  *
  *  Concatenation---Returns a new <code>String</code> containing
  *  <i>other_str</i> concatenated to <i>str</i>. 
 

  *
  *     "Hello from " + self.to_s   #=> "Hello from main"
  */

VALUE
rb_str_plus(VALUE str1, VALUE str2)
{
     VALUE str3;
     rb_encoding *enc;

     StringValue(str2);
     enc = rb_enc_check(str1, str2);
     str3 = rb_str_new(0, RSTRING_LEN(str1)+RSTRING_LEN(str2));
     memcpy(RSTRING_PTR(str3), RSTRING_PTR(str1), RSTRING_LEN(str1));
     memcpy(RSTRING_PTR(str3) + RSTRING_LEN(str1),
            RSTRING_PTR(str2), RSTRING_LEN(str2));
     RSTRING_PTR(str3)[RSTRING_LEN(str3)] = '\0';

     if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
         OBJ_TAINT(str3);
     ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
                            ENC_CODERANGE_AND(ENC_CODERANGE(str1), 
ENC_CODERANGE(str2)));
     return str3;
}

/*
  *  call-seq:
  *     str % arg   => new_str 
 

  *
  *  Format---Uses <i>str</i> as a format specification, and returns the 
result
  *  of applying it to <i>arg</i>. If the format specification contains 
more than
  *  one substitution, then <i>arg</i> must be an <code>Array</code> 
containing
  *  the values to be substituted. See <code>Kernel::sprintf</code> for 
details
  *  of the format string.
  *
  *     "%05d" % 123                              #=> "00123"
  *     "%-5s: %08x" % [ "ID", self.object_id ]   #=> "ID   : 200e14d6"
  */

static VALUE
rb_str_format_m(VALUE str, VALUE arg)
{
     volatile VALUE tmp = rb_check_array_type(arg);

     if (!NIL_P(tmp)) {
         return rb_str_format(RARRAY_LEN(tmp), RARRAY_PTR(tmp), str);
     }
     return rb_str_format(1, &arg, str);
}



Berikut ini source code di source code rubinius  (ya, pakai Ruby, dan 
silakan spec'ing dan bm sendiri)

File: /home/arie/Documents/sources/rubinius/kernel/core/string.rb



# call-seq:
#   str % arg   => new_str 
 

#
# Format---Uses <i>self</i> as a format specification, and returns the 
result
# of applying it to <i>arg</i>. If the format specification contains 
more than
# one substitution, then <i>arg</i> must be an <code>Array</code> containing
# the values to be substituted. See <code>Kernel::sprintf</code> for details
# of the format string.
#
#   "%05d" % 123                       #=> "00123"
#   "%-5s: %08x" % [ "ID", self.id ]   #=> "ID   : 200e14d6"
def %(args)
   Sprintf.new(self, *args).parse
end

# Concatenation --- Returns a new <code>String</code> containing
# <i>other</i> concatenated to <i>string</i>.
# 
 

#   "Hello from " + self.to_s   #=> "Hello from main"
def +(other)
   r = "#{self}#{StringValue(other)}"
   r.taint if self.tainted? or other.tainted?
   r
end


-- 
http://tinyurl.com/5w6lve

                        "Smalltalk, isn't it dead?" Hardly.
    Randal Schwartz on Smalltalk

Kirim email ke