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/