[前][次][番号順一覧][スレッド一覧]

ruby-changes:45403

From: normal <ko1@a...>
Date: Tue, 31 Jan 2017 11:19:03 +0900 (JST)
Subject: [ruby-changes:45403] normal:r57476 (trunk): time.c (time_strftime): avoid garbage in common case

normal	2017-01-31 11:18:58 +0900 (Tue, 31 Jan 2017)

  New Revision: 57476

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=57476

  Log:
    time.c (time_strftime): avoid garbage in common case
    
    strftime format strings which are dynamically-generated will benefit
    from avoiding garbage, here.
    
    * time.c (time_strftime): use rb_str_tmp_frozen_{acquire,release}
    * test/ruby/test_time.rb (test_strftime_no_hidden_garbage): new test

  Modified files:
    trunk/test/ruby/test_time.rb
    trunk/time.c
Index: test/ruby/test_time.rb
===================================================================
--- test/ruby/test_time.rb	(revision 57475)
+++ test/ruby/test_time.rb	(revision 57476)
@@ -1090,6 +1090,17 @@ class TestTime < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time.rb#L1090
     assert_equal("366", t.strftime("%j"))
   end
 
+  def test_strftime_no_hidden_garbage
+    fmt = %w(Y m d).map { |x| "%#{x}" }.join('-') # defeats optimization
+    t = Time.at(0)
+    ObjectSpace.count_objects(res = {}) # creates strings on first call
+    before = ObjectSpace.count_objects(res)[:T_STRING]
+    val = t.strftime(fmt)
+    after = ObjectSpace.count_objects(res)[:T_STRING]
+    assert_equal before + 1, after, 'only new string is the created one'
+    assert_equal '1970-01-01', val
+  end
+
   def test_num_exact_error
     bad = EnvUtil.labeled_class("BadValue").new
     x = EnvUtil.labeled_class("Inexact") do
Index: time.c
===================================================================
--- time.c	(revision 57475)
+++ time.c	(revision 57476)
@@ -4422,6 +4422,7 @@ time_strftime(VALUE time, VALUE format) https://github.com/ruby/ruby/blob/trunk/time.c#L4422
     const char *fmt;
     long len;
     rb_encoding *enc;
+    VALUE tmp;
 
     GetTimeval(time, tobj);
     MAKE_TM(time, tobj);
@@ -4429,9 +4430,9 @@ time_strftime(VALUE time, VALUE format) https://github.com/ruby/ruby/blob/trunk/time.c#L4430
     if (!rb_enc_str_asciicompat_p(format)) {
 	rb_raise(rb_eArgError, "format should have ASCII compatible encoding");
     }
-    format = rb_str_new4(format);
-    fmt = RSTRING_PTR(format);
-    len = RSTRING_LEN(format);
+    tmp = rb_str_tmp_frozen_acquire(format);
+    fmt = RSTRING_PTR(tmp);
+    len = RSTRING_LEN(tmp);
     enc = rb_enc_get(format);
     if (len == 0) {
 	rb_warning("strftime called with empty format string");
@@ -4440,6 +4441,7 @@ time_strftime(VALUE time, VALUE format) https://github.com/ruby/ruby/blob/trunk/time.c#L4441
     else {
 	VALUE str = rb_strftime_alloc(fmt, len, enc, &tobj->vtm, tobj->timew,
 				      TIME_UTC_P(tobj));
+	rb_str_tmp_frozen_release(format, tmp);
 	if (!str) rb_raise(rb_eArgError, "invalid format: %"PRIsVALUE, format);
 	return str;
     }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]