Add optimization for creating zerofill string

```
require 'benchmark'
n = 1 * 1024 * 1024 * 1024
Benchmark.bmbm do |x|
  x.report("*") { 0.chr * n }
  x.report("ljust") { String.new(capacity: n).ljust(n, "\0") }
end
```

Before

```% ./ruby test.rb
Rehearsal -----------------------------------------
*       0.358396   0.392753   0.751149 (  1.134231)
ljust   0.203277   0.389223   0.592500 (  0.594816)
-------------------------------- total: 1.343649sec

            user     system      total        real
*       0.282647   0.304600   0.587247 (  0.589205)
ljust   0.201834   0.283801   0.485635 (  0.487617)
```

After

```% ./ruby test.rb
Rehearsal -----------------------------------------
*       0.000522   0.000021   0.000543 (  0.000534)
ljust   0.208551   0.321030   0.529581 (  0.542083)
-------------------------------- total: 0.530124sec

            user     system      total        real
*       0.000069   0.000006   0.000075 (  0.000069)
ljust   0.206698   0.301032   0.507730 (  0.517674)
```

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59614 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2017-08-17 16:34:40 +00:00
parent 0db193f98d
commit d067b263c7

View File

@ -1905,6 +1905,18 @@ rb_str_times(VALUE str, VALUE times)
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
str2 = str_alloc(rb_obj_class(str));
if (!STR_EMBEDDABLE_P(len, 1)) {
RSTRING(str2)->as.heap.aux.capa = len;
RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1);
STR_SET_NOEMBED(str2);
}
STR_SET_LEN(str2, len);
rb_enc_copy(str2, str);
OBJ_INFECT(str2, str);
return str2;
}
if (len && LONG_MAX/len < RSTRING_LEN(str)) {
rb_raise(rb_eArgError, "argument too big");
}