mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Improve String#slice!
performance
Instead of searching twice to extract and to delete, extract and delete the found position at the first search. This makes faster nearly twice, for regexps and strings. | |compare-ruby|built-ruby| |:-------------|-----------:|---------:| |regexp-short | 2.143M| 3.918M| |regexp-long | 105.162k| 205.410k| |string-short | 3.789M| 7.964M| |string-long | 1.301M| 2.457M|
This commit is contained in:
parent
0dd6f020fc
commit
05229cef45
Notes:
git
2020-01-31 17:56:55 +09:00
2 changed files with 80 additions and 15 deletions
11
benchmark/string_slice.yml
Normal file
11
benchmark/string_slice.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
prelude: |
|
||||||
|
long_string = "x"*1000+"-hår"
|
||||||
|
benchmark:
|
||||||
|
regexp-short: |
|
||||||
|
"x-hår".slice!(/-(.)(.)(.)/, 3)
|
||||||
|
regexp-long: |
|
||||||
|
long_string.dup.slice!(/-(.)(.)(.)/, 3)
|
||||||
|
string-short: |
|
||||||
|
"x-hår".slice!("r")
|
||||||
|
string-long: |
|
||||||
|
long_string.dup.slice!("r")
|
84
string.c
84
string.c
|
@ -215,14 +215,6 @@ str_make_independent(VALUE str)
|
||||||
/* symbols for [up|down|swap]case/capitalize options */
|
/* symbols for [up|down|swap]case/capitalize options */
|
||||||
static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
|
static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
|
||||||
|
|
||||||
static const struct RString empty_fake_string = {
|
|
||||||
{
|
|
||||||
T_STRING | STR_FAKESTR |
|
|
||||||
ENC_CODERANGE_7BIT | (ENCINDEX_US_ASCII << ENCODING_SHIFT)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#define empty_string ((VALUE)&empty_fake_string)
|
|
||||||
|
|
||||||
static rb_encoding *
|
static rb_encoding *
|
||||||
get_actual_encoding(const int encidx, VALUE str)
|
get_actual_encoding(const int encidx, VALUE str)
|
||||||
{
|
{
|
||||||
|
@ -4889,16 +4881,78 @@ rb_str_insert(VALUE str, VALUE idx, VALUE str2)
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
|
rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
|
||||||
{
|
{
|
||||||
VALUE result;
|
VALUE result = Qnil;
|
||||||
VALUE buf[3];
|
VALUE indx;
|
||||||
|
long beg, len = 1;
|
||||||
|
char *p;
|
||||||
|
|
||||||
rb_check_arity(argc, 1, 2);
|
rb_check_arity(argc, 1, 2);
|
||||||
MEMCPY(buf, argv, VALUE, argc);
|
|
||||||
str_modify_keep_cr(str);
|
str_modify_keep_cr(str);
|
||||||
result = rb_str_aref_m(argc, buf, str);
|
indx = argv[0];
|
||||||
if (!NIL_P(result)) {
|
if (RB_TYPE_P(indx, T_REGEXP)) {
|
||||||
buf[argc] = empty_string;
|
if (rb_reg_search(indx, str, 0, 0) < 0) return Qnil;
|
||||||
rb_str_aset_m(argc+1, buf, str);
|
VALUE match = rb_backref_get();
|
||||||
|
struct re_registers *regs = RMATCH_REGS(match);
|
||||||
|
int nth = 0;
|
||||||
|
if (argc > 1 && (nth = rb_reg_backref_number(match, argv[1])) < 0) {
|
||||||
|
if ((nth += regs->num_regs) <= 0) return Qnil;
|
||||||
|
}
|
||||||
|
else if (nth >= regs->num_regs) return Qnil;
|
||||||
|
beg = BEG(nth);
|
||||||
|
len = END(nth) - beg;
|
||||||
|
subseq:
|
||||||
|
result = rb_str_new_with_class(str, RSTRING_PTR(str)+beg, len);
|
||||||
|
rb_enc_cr_str_copy_for_substr(result, str);
|
||||||
|
}
|
||||||
|
else if (argc == 2) {
|
||||||
|
beg = NUM2LONG(indx);
|
||||||
|
len = NUM2LONG(argv[1]);
|
||||||
|
num_index:
|
||||||
|
if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
|
||||||
|
beg = p - RSTRING_PTR(str);
|
||||||
|
goto subseq;
|
||||||
|
}
|
||||||
|
else if (FIXNUM_P(indx)) {
|
||||||
|
beg = FIX2LONG(indx);
|
||||||
|
if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
|
||||||
|
if (!len) return Qnil;
|
||||||
|
beg = p - RSTRING_PTR(str);
|
||||||
|
goto subseq;
|
||||||
|
}
|
||||||
|
else if (RB_TYPE_P(indx, T_STRING)) {
|
||||||
|
beg = rb_str_index(str, indx, 0);
|
||||||
|
if (beg == -1) return Qnil;
|
||||||
|
len = RSTRING_LEN(indx);
|
||||||
|
result = rb_str_dup(indx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (rb_range_beg_len(indx, &beg, &len, str_strlen(str, NULL), 0)) {
|
||||||
|
case Qnil:
|
||||||
|
return Qnil;
|
||||||
|
case Qfalse:
|
||||||
|
beg = NUM2LONG(indx);
|
||||||
|
goto num_index;
|
||||||
|
default:
|
||||||
|
goto num_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
if (beg == 0) {
|
||||||
|
rb_str_drop_bytes(str, len);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char *sptr = RSTRING_PTR(str);
|
||||||
|
long slen = RSTRING_LEN(str);
|
||||||
|
if (beg + len > slen) /* pathological check */
|
||||||
|
len = slen - beg;
|
||||||
|
memmove(sptr + beg,
|
||||||
|
sptr + beg + len,
|
||||||
|
slen - (beg + len));
|
||||||
|
slen -= len;
|
||||||
|
STR_SET_LEN(str, slen);
|
||||||
|
TERM_FILL(&sptr[slen], TERM_LEN(str));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue