# Optimize range space

Range e\$B\$N%a%b%j>CHq\$r@aLs\$9\$k\$N\$O\$I\$&\$G\$7\$g\$&\$+!#e(B

Range e\$B\$O8=:_e(B T_OBJECT e\$B\$G!"%O%C%7%e\$r;H\$C\$F>pJs\$rJ];}\$7\$^\$9!#e(B

e\$B\$7\$+\$7!"DL>o!"e(Bbegin, end, excl e\$B\$Ne(B
3e\$B\$D\$N%\$%s%9%?%s%9JQ?t\$7\$+e(B
e\$B;H\$\$\$^\$;\$s!#e(B

e\$B\$=\$&\$9\$k\$H!"%a%b%j\$Oe(B 3 word e\$B\$"\$l\$P==J,\$G!“e(BRVALUE
e\$B\$KKd\$a9~\$ae(B
e\$B\$k\$O\$:\$G\$9\$,!”%O%C%7%e\$r;H\$C\$F\$\$\$k\$?\$a!“e(Bst_table e\$B\$*\$h\$Se(B bins
e\$B\$r30It\$K3NJ]\$9\$k\$3\$H\$K\$J\$C\$F\$\$\$^\$9!#e(B
(st e\$B\$G\$Ne(B bins e\$B\$X\$NKd\$a9~\$_\$r9T\$&0JA0\$O!”\$5\$i\$Ke(B
struct st_table_entry e\$B\$,e(B 3e\$B\$DI,MW\$G\$7\$?e(B)

e\$B\$3\$l\$O\$"\$^\$j\$KL5BL\$J\$N\$Ge(B Range e\$B\$re(B T_STRUCT
e\$B\$K\$7\$FKd\$a9~\$s\$Ge(B
e\$B\$_\$?\$N\$G\$9\$,\$I\$&\$G\$7\$g\$&\$+!#e(B

e\$B\$?\$@!"e(BT_STRUCT e\$B\$KJQ\$(\$k\$H!"e(Bmarshal e\$B\$,LdBj\$K\$J\$j\$^\$9!#e(B
marshal e\$B\$N8_49@-\$OJ];}\$7\$?\$\$\$N\$G!"FbIt\$N<BBN\$H\$O0[\$J\$k7A\$Ge(B
e\$B\$7\$?%G!<%?\$Oe(B T_OBJECT e\$B\$K\$J\$k\$h\$&\$K\$7\$^\$7\$?!#e(B

# Index: eval_method.ci

— eval_method.ci (revision 13328)
+++ eval_method.ci (working copy)
@@ -192,6 +192,19 @@
}

+rb_alloc_func_t
+rb_get_alloc_func(VALUE klass)
+{

• NODE *n;
• Check_Type(klass, T_CLASS);
• n = rb_method_node(CLASS_OF(klass), ID_ALLOCATOR);
• if (!n) return 0;
• if (nd_type(n) != NODE_METHOD) return 0;
• n = n->nd_body;
• if (nd_type(n) != NODE_CFUNC) return 0;
• return n->nd_cfnc;
+}

# — include/ruby/intern.h (revision 13328) +++ include/ruby/intern.h (working copy) @@ -218,8 +218,10 @@#define rb_disable_super(klass, name) ((void)0)#define rb_enable_super(klass, name) ((void)0)#define HAVE_RB_DEFINE_ALLOC_FUNC 1 -void rb_define_alloc_func(VALUE, VALUE (*)(VALUE)); +typedef VALUE (rb_alloc_func_t)(VALUE); +void rb_define_alloc_func(VALUE, rb_alloc_func_t); void rb_undef_alloc_func(VALUE); +rb_alloc_func_t rb_get_alloc_func(VALUE); void rb_clear_cache(void); void rb_clear_cache_by_class(VALUE); void rb_alias(VALUE, ID, ID); @@ -355,6 +357,7 @@ / marshal.c */ VALUE rb_marshal_dump(VALUE, VALUE); VALUE rb_marshal_load(VALUE); +void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (loader)(VALUE, VALUE)); / numeric.c */ void rb_num_zerodiv(void); VALUE rb_num_coerce_bin(VALUE, VALUE); Index: range.c

— range.c (revision 13328)
+++ range.c (working copy)
@@ -15,10 +15,34 @@
VALUE rb_cRange;
static ID id_cmp, id_succ, id_beg, id_end, id_excl;

-#define EXCL® RTEST(rb_ivar_get(®, id_excl))
-#define SET_EXCL(r,v) rb_ivar_set(®, id_excl, (v) ? Qtrue : Qfalse)
+#define RANGE_BEG® (RSTRUCT®->as.ary[0])
+#define RANGE_END® (RSTRUCT®->as.ary[1])
+#define RANGE_EXCL® (RSTRUCT®->as.ary[2])

+#define EXCL® RTEST(RANGE_EXCL®)
+#define SET_EXCL(r,v) (RSTRUCT®->as.ary[2] = (v) ? Qtrue : Qfalse)
+
+#define FL_INITIALIZED FL_USER3
+
static VALUE
+range_alloc(VALUE klass)
+{

• long n;
• NEWOBJ(r, struct RStruct);
• OBJSETUP(r, klass, T_STRUCT);
• n = 3;
• RBASIC®->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
• rb_mem_clear(r->as.ary, n);
• RBASIC®->flags &= ~FL_INITIALIZED;
• return (VALUE)r;
+}

+static VALUE
range_failed(void)
{
@@ -48,8 +72,8 @@
}

`````` SET_EXCL(range, exclude_end);
``````
• rb_ivar_set(range, id_beg, beg);
• rb_ivar_set(range, id_end, end);
• RSTRUCT(range)->as.ary[0] = beg;
• RSTRUCT(range)->as.ary[1] = end;
}

VALUE
@@ -77,9 +101,10 @@

`````` rb_scan_args(argc, argv, "21", &beg, &end, &flags);
/* Ranges are immutable, so that they should be initialized only
``````

once. */

• if (rb_ivar_defined(range, id_beg)) {
• if (RBASIC(range)->flags & FL_INITIALIZED) {
rb_name_error(rb_intern(“initialize”), “`initialize’ called twice”);
}
• RBASIC(range)->flags |= FL_INITIALIZED;
range_init(range, beg, end, RTEST(flags));
return Qnil;
}
@@ -121,9 +146,9 @@
if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
return Qfalse;
• if (!rb_equal(rb_ivar_get(range, id_beg), rb_ivar_get(obj,
id_beg)))
• if (!rb_equal(RANGE_BEG(range), RANGE_BEG(obj)))
return Qfalse;
• if (!rb_equal(rb_ivar_get(range, id_end), rb_ivar_get(obj,
id_end)))
• if (!rb_equal(RANGE_END(range), RANGE_END(obj)))
return Qfalse;

if (EXCL(range) != EXCL(obj))
@@ -183,9 +208,9 @@
if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
return Qfalse;

• if (!rb_eql(rb_ivar_get(range, id_beg), rb_ivar_get(obj, id_beg)))
• if (!rb_eql(RANGE_BEG(range), RANGE_BEG(obj)))
return Qfalse;
• if (!rb_eql(rb_ivar_get(range, id_end), rb_ivar_get(obj, id_end)))
• if (!rb_eql(RANGE_END(range), RANGE_END(obj)))
return Qfalse;

if (EXCL(range) != EXCL(obj))
@@ -209,9 +234,9 @@
long hash = EXCL(range);
VALUE v;

• v = rb_hash(rb_ivar_get(range, id_beg));
• v = rb_hash(RANGE_BEG(range));
hash ^= v << 1;
• v = rb_hash(rb_ivar_get(range, id_end));
• v = rb_hash(RANGE_END(range));
hash ^= v << 9;
hash ^= EXCL(range) << 24;

@@ -289,8 +314,8 @@

`````` RETURN_ENUMERATOR(range, argc, argv);
``````
• b = rb_ivar_get(range, id_beg);
• e = rb_ivar_get(range, id_end);
• b = RANGE_BEG(range);

• e = RANGE_END(range);
if (rb_scan_args(argc, argv, “01”, &step) == 0) {
step = INT2FIX(1);
}
@@ -382,8 +407,8 @@

RETURN_ENUMERATOR(range, 0, 0);

• beg = rb_ivar_get(range, id_beg);
• end = rb_ivar_get(range, id_end);
• beg = RANGE_BEG(range);

• end = RANGE_END(range);

if (!rb_respond_to(beg, id_succ)) {
rb_raise(rb_eTypeError, “can’t iterate from %s”,
@@ -423,7 +448,7 @@
static VALUE
range_first(VALUE range)
{

• return rb_ivar_get(range, id_beg);
• return RANGE_BEG(range);
}

@@ -442,7 +467,7 @@
static VALUE
range_last(VALUE range)
{

• return rb_ivar_get(range, id_end);
• return RANGE_END(range);
}

/*
@@ -464,8 +489,8 @@
return rb_call_super(0, 0);
}
else {

• VALUE b = rb_ivar_get(range, id_beg);
• VALUE e = rb_ivar_get(range, id_end);
• VALUE b = RANGE_BEG(range);

• VALUE e = RANGE_END(range);
int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);

if (c > 0 || (c == 0 && EXCL(range)))
@@ -489,14 +514,14 @@
static VALUE
range_max(VALUE range)
{

• VALUE e = rb_ivar_get(range, id_end);
• VALUE e = RANGE_END(range);
int ip = FIXNUM_P(e) || rb_obj_is_kind_of(e, rb_cInteger);

if (rb_block_given_p() || (EXCL(range) && !ip)) {
return rb_call_super(0, 0);
}
else {

• VALUE b = rb_ivar_get(range, id_beg);
• VALUE b = RANGE_BEG(range);
int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);

if (c > 0)
@@ -519,8 +544,8 @@
long beg, end, excl;

if (rb_obj_is_kind_of(range, rb_cRange)) {

• b = rb_ivar_get(range, id_beg);
• e = rb_ivar_get(range, id_end);
• b = RANGE_BEG(range);
• e = RANGE_END(range);
excl = EXCL(range);
}
else {
@@ -578,8 +603,8 @@
{
VALUE str, str2;
• str = rb_obj_as_string(rb_ivar_get(range, id_beg));
• str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
• str = rb_obj_as_string(RANGE_BEG(range));
• str2 = rb_obj_as_string(RANGE_END(range));
str = rb_str_dup(str);
rb_str_cat(str, “…”, EXCL(range) ? 3 : 2);
rb_str_append(str, str2);
@@ -616,8 +641,8 @@
{
VALUE str, str2;
• str = rb_inspect(rb_ivar_get(range, id_beg));
• str2 = rb_inspect(rb_ivar_get(range, id_end));
• str = rb_inspect(RANGE_BEG(range));
• str2 = rb_inspect(RANGE_END(range));
str = rb_str_dup(str);
rb_str_cat(str, “…”, EXCL(range) ? 3 : 2);
rb_str_append(str, str2);
@@ -668,8 +693,8 @@
static VALUE
range_include(VALUE range, VALUE val)
{
• VALUE beg = rb_ivar_get(range, id_beg);
• VALUE end = rb_ivar_get(range, id_end);
• VALUE beg = RANGE_BEG(range);
• VALUE end = RANGE_END(range);
int nv = FIXNUM_P(beg) || FIXNUM_P(end) ||
rb_obj_is_kind_of(beg, rb_cNumeric) ||
rb_obj_is_kind_of(end, rb_cNumeric);
@@ -711,8 +736,8 @@
{
VALUE beg, end;
• beg = rb_ivar_get(range, id_beg);
• end = rb_ivar_get(range, id_end);
• beg = RANGE_BEG(range);
• end = RANGE_END(range);
if (r_le(beg, val)) {
if (EXCL(range)) {
if (r_lt(val, end))
@@ -726,7 +751,34 @@
return Qfalse;
}

+static VALUE
+range_dumper(VALUE range)
+{

• VALUE v;

• NEWOBJ(m, struct RObject);

• OBJSETUP(m, rb_cObject, T_OBJECT);

• v = (VALUE)m;

• rb_ivar_set(v, id_excl, EXCL(range) ? Qtrue : Qfalse);

• rb_ivar_set(v, id_beg, RANGE_BEG(range));

• rb_ivar_set(v, id_end, RANGE_END(range));

• return v;
+}

+static VALUE
+{

• if (TYPE(obj) != T_OBJECT || RBASIC(obj)->klass != rb_cObject) {
• ``````   rb_raise(rb_eTypeError, "not a dumped range object");
``````
• }
• RSTRUCT(range)->as.ary[0] = rb_ivar_get(obj, id_beg);
• RSTRUCT(range)->as.ary[1] = rb_ivar_get(obj, id_end);
• SET_EXCL(range, RTEST(rb_ivar_get(obj, id_excl)));
• return range;
+}

/* A `Range` represents an interval—a set of values with
a

• start and an end. Ranges may be constructed using the
• s`…`e and
@@ -782,8 +834,25 @@
void
Init_Range(void)
{
• VALUE members;
• id_cmp = rb_intern("<=>");
• id_succ = rb_intern(“succ”);
• id_beg = rb_intern(“begin”);
• id_end = rb_intern(“end”);
• id_excl = rb_intern(“excl”);
• rb_cRange = rb_define_class(“Range”, rb_cObject);
• /* compatibility for rb_struct_members, etc. */
• members = rb_ary_new3(3, ID2SYM(id_beg), ID2SYM(id_end),
ID2SYM(id_excl));
• OBJ_FREEZE(members);
• rb_iv_set(rb_cRange, “size”, INT2FIX(3));
• rb_iv_set(rb_cRange, “members”, members);
• rb_define_alloc_func(rb_cRange, range_alloc);
• rb_marshal_define_compat(rb_cRange, rb_cObject, range_dumper,
rb_define_method(rb_cRange, “initialize”, range_initialize, -1);
rb_define_method(rb_cRange, “==”, range_eq, 1);
rb_define_method(rb_cRange, “===”, range_eqq, 1);
@@ -807,9 +876,4 @@
rb_define_method(rb_cRange, “include?”, range_include, 1);
rb_define_method(rb_cRange, “cover?”, range_cover, 1);
• id_cmp = rb_intern("<=>");
• id_succ = rb_intern(“succ”);
• id_beg = rb_intern(“begin”);
• id_end = rb_intern(“end”);
• id_excl = rb_intern(“excl”);
}
Index: inits.c
===================================================================
— inits.c (revision 13328)
+++ inits.c (working copy)
@@ -76,6 +76,7 @@
Init_Struct();
Init_Regexp();
Init_pack();
• Init_marshal();
Init_Range();
Init_IO();
Init_Dir();
@@ -88,7 +89,6 @@
Init_Binding();
Init_Math();
Init_GC();
• Init_marshal();
Init_Enumerator();
Init_VM();
Init_ISeq();
Index: marshal.c
===================================================================
— marshal.c (revision 13328)
+++ marshal.c (working copy)
@@ -82,12 +82,45 @@
static ID s_getc, s_read, s_write, s_binmode;

+typedef struct {

• VALUE newclass;
• VALUE oldclass;
• VALUE (*dumper)(VALUE);
+} marshal_compat_t;

+static st_table *compat_allocator_tbl;
+
+void
+rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE
+{

• marshal_compat_t *compat;
• rb_alloc_func_t allocator = rb_get_alloc_func(newclass);
• if (!allocator) {
• ``````   rb_raise(rb_eTypeError, "no allocator");
``````
• }
• compat = ALLOC(marshal_compat_t);
• compat->newclass = Qnil;
• compat->oldclass = Qnil;
• compat->newclass = newclass;
• compat->oldclass = oldclass;
• compat->dumper = dumper;
• st_insert(compat_allocator_tbl, (st_data_t)allocator,
(st_data_t)compat);
+}

struct dump_arg {
VALUE obj;
VALUE str, dest;
st_table *symbols;
st_table *data;
int taint;

• st_table *compat_tbl;
};

struct dump_call_arg {
@@ -363,8 +396,13 @@
{
volatile VALUE p;
char *path;

• VALUE real_obj;
• VALUE klass;
• VALUE klass = CLASS_OF(obj);
• if (st_lookup(arg->compat_tbl, (st_data_t)obj,
(st_data_t*)&real_obj)) {
• ``````   obj = real_obj;
``````
• }
• klass = CLASS_OF(obj);
w_extended(klass, arg, check);
w_byte(type, arg);
p = class2path(rb_class_real(klass));
@@ -459,6 +497,19 @@
if (OBJ_TAINTED(obj)) arg->taint = Qtrue;

+

• ``````   {
``````
• ``````       marshal_compat_t *compat;
``````
• ``````       rb_alloc_func_t allocator =
``````

rb_get_alloc_func(RBASIC(obj)->klass);

• ``````       if (st_lookup(compat_allocator_tbl,
``````
• ``````                     (st_data_t)allocator,
``````
• ``````                     (st_data_t*)&compat)) {
``````
• ``````           VALUE real_obj = obj;
``````
• ``````           obj = compat->dumper(real_obj);
``````
• ``````           st_insert(arg->compat_tbl, (st_data_t)obj,
``````

(st_data_t)real_obj);

• ``````       }
``````
• ``````   }
``````
• if (rb_respond_to(obj, s_mdump)) {
VALUE v;

@@ -720,6 +771,7 @@
arg.symbols = st_init_numtable();
arg.data = st_init_numtable();
arg.taint = Qfalse;

• arg.compat_tbl = st_init_numtable();
c_arg.obj = obj;
c_arg.arg = &arg;
c_arg.limit = limit;
@@ -739,6 +791,7 @@
VALUE data;
VALUE proc;
int taint;
• st_table *compat_tbl;
};

static VALUE r_entry(VALUE v, struct load_arg *arg);
@@ -899,14 +952,41 @@
static VALUE
{

• rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
• if (arg->taint) OBJ_TAINT(v);
• VALUE real_obj = Qundef;
• if (st_lookup(arg->compat_tbl, v, (st_data_t*)&real_obj)) {
• ``````   rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)),
``````

real_obj);

• }
• else {
• ``````   rb_hash_aset(arg->data, INT2FIX(RHASH_SIZE(arg->data)), v);
``````
• }
• if (arg->taint) {
• ``````   OBJ_TAINT(v);
``````
• ``````   if (real_obj != Qundef)
``````
• ``````       OBJ_TAINT(real_obj);
``````
• }
if (arg->proc) {
v = rb_funcall(arg->proc, rb_intern(“call”), 1, v);
}
return v;
}

+static VALUE
+{

• VALUE real_obj;
• marshal_compat_t *compat;
• if (st_lookup(arg->compat_tbl, v, &real_obj)) {
• ``````   rb_alloc_func_t allocator =
``````

rb_get_alloc_func(CLASS_OF(real_obj));

• ``````   st_data_t key = v;
``````
• ``````   if (st_lookup(compat_allocator_tbl, (st_data_t)allocator,
``````

(st_data_t*)&compat)) {

• ``````       compat->loader(real_obj, v);
``````
• ``````   }
``````
• ``````   st_delete(arg->compat_tbl, &key, 0);
``````
• ``````   return real_obj;
``````
• }
• return v;
+}

static void
{
@@ -945,6 +1025,26 @@
}

static VALUE
+obj_alloc_by_path(const char *path, struct load_arg *arg)
+{

• VALUE klass;
• marshal_compat_t *compat;
• rb_alloc_func_t allocator;
• klass = path2class(path);
• allocator = rb_get_alloc_func(klass);
• if (st_lookup(compat_allocator_tbl, (st_data_t)allocator,
(st_data_t*)&compat)) {
• ``````   VALUE real_obj = rb_obj_alloc(klass);
``````
• ``````   VALUE obj = rb_obj_alloc(compat->oldclass);
``````
• ``````   st_insert(arg->compat_tbl, (st_data_t)obj,
``````

(st_data_t)real_obj);

• ``````   return obj;
``````
• }
• return rb_obj_alloc(klass);
+}

+static VALUE
r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
{
VALUE v = Qnil;
@@ -1049,6 +1149,7 @@
}
v = rb_float_new(d);
v = r_entry(v, arg);

• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1094,11 +1195,13 @@
}
v = rb_big_norm((VALUE)big);
v = r_entry(v, arg);

• ``````       v = r_leave(v, arg);
``````

}
break;

`````` case TYPE_STRING:
``````

v = r_entry(r_string(arg), arg);

• ``````   v = r_leave(v, arg);
``````

break;

`````` case TYPE_REGEXP:
``````

@@ -1106,6 +1209,7 @@
volatile VALUE str = r_bytes(arg);
int options = r_byte(arg);
v = r_entry(rb_reg_new(str, options), arg);

• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1118,6 +1222,7 @@
while (len–) {
rb_ary_push(v, r_object(arg));
}

• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1136,6 +1241,7 @@
if (type == TYPE_HASH_DEF) {
RHASH(v)->ifnone = r_object(arg);
}

• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1170,6 +1276,7 @@
}
rb_struct_aset(v, LONG2FIX(i), r_object(arg));
}

• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1189,6 +1296,7 @@
}
v = rb_funcall(klass, s_load, 1, data);
v = r_entry(v, arg);

• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1211,19 +1319,19 @@
v = r_entry(v, arg);
data = r_object(arg);

• ``````       v = r_leave(v, arg);
``````

}
break;

`````` case TYPE_OBJECT:
``````

{

• `````` VALUE klass = path2class(r_unique(arg));
``````
• `````` v = rb_obj_alloc(klass);
``````
• ``````       v = obj_alloc_by_path(r_unique(arg), arg);
if (TYPE(v) != T_OBJECT) {
``````
rb_raise(rb_eArgError, “dump format error”);
}
v = r_entry(v, arg);
r_ivar(v, arg);
• `````` v = r_leave(v, arg);
``````
}
break;

@@ -1251,6 +1359,7 @@
rb_class2name(klass));
}
rb_funcall(v, s_load_data, 1, r_object0(arg, 0, extmod));

• ``````      v = r_leave(v, arg);
}
break;
``````

@@ -1260,6 +1369,7 @@

``````   v = rb_path2class(RSTRING_PTR(str));
v = r_entry(v, arg);
``````
• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1269,6 +1379,7 @@

``````   v = path2class(RSTRING_PTR(str));
v = r_entry(v, arg);
``````
• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1278,6 +1389,7 @@

``````   v = path2module(RSTRING_PTR(str));
v = r_entry(v, arg);
``````
• ``````       v = r_leave(v, arg);
``````
}
break;

@@ -1350,6 +1462,7 @@
}
arg.src = port;
arg.offset = 0;

• arg.compat_tbl = st_init_numtable();

major = r_byte(&arg);
minor = r_byte(&arg);
@@ -1429,6 +1542,8 @@

rb_define_const(rb_mMarshal, “MAJOR_VERSION”,
INT2FIX(MARSHAL_MAJOR));
rb_define_const(rb_mMarshal, “MINOR_VERSION”,
INT2FIX(MARSHAL_MINOR));

• compat_allocator_tbl = st_init_numtable();
}

VALUE

In article [email protected],
Tanaka A. [email protected] writes:

Range e\$B\$N%a%b%j>CHq\$r@aLs\$9\$k\$N\$O\$I\$&\$G\$7\$g\$&\$+!#e(B

e\$B\$I\$N\$/\$i\$\$@aLs\$G\$-\$k\$N\$+B,\$C\$F\$_\$^\$7\$?!#e(B

e\$B@aLs\$9\$kA0\$O!"0J2<\$N\$h\$&\$K!"e(B1000000e\$B8D\$Ne(B range
e\$B\$r@8@.\$9\$k\$He(B
106Mbytes e\$B\$[\$II,MW\$G\$9!#e(B

% time ./ruby -e ‘a = []; 1000000.times {|i| a << (i…i) }
VmPeak: 105604 kB
VmSize: 105604 kB
VmLck: 0 kB
VmHWM: 102596 kB
VmData: 102772 kB
VmStk: 84 kB
VmExe: 1176 kB
VmLib: 1492 kB
VmPTE: 116 kB
./ruby -e 7.61s user 0.20s system 98% cpu 7.952 total

e\$B@aLs\$9\$k\$H!"0J2<\$N\$h\$&\$K!"e(B 35Mbytes e\$B\$[\$I\$G:Q\$_\$^\$9!#e(B

% time ./ruby -e ‘a = []; 1000000.times {|i| a << (i…i) }
VmPeak: 35416 kB
VmSize: 35416 kB
VmLck: 0 kB
VmHWM: 32424 kB
VmData: 32588 kB
VmStk: 84 kB
VmExe: 1176 kB
VmLib: 1492 kB
VmPTE: 48 kB
./ruby -e 3.18s user 0.06s system 97% cpu 3.332 total

e\$B\$D\$^\$j!";HMQ%a%b%j\$OH>J,0J2<\$K\$J\$j!"3d9g\$H\$7\$F\$OLse(B 6e\$B3d:o8:\$Ge(B
e\$B\$-\$F\$\$\$^\$9!#e(B

e\$B\$5\$i\$K!"\$+\$+\$C\$?;~4V\$b!"e(B8e\$BIC\$+\$ie(B
3.3e\$BIC\$/\$i\$\$\$H8:\$j!"G\0J>e\$Ke(B
e\$B9bB.2=\$7\$F\$\$\$^\$9!#e(B

e\$B\$3\$&\$7\$F\$_\$k\$H!“\$\$\$^\$Ne(B Range e\$B\$,\$\$\$+\$KL5BL\$J\$3\$H\$r\$7\$F\$\$\$k\$+e(B
e\$B\$H\$\$\$&\$N\$,\$o\$+\$k\$N\$G\$9\$,!”\$\$\$+\$,\$G\$7\$g\$&\$+!#e(B

e\$B\$^\$D\$b\$He(B e\$B\$f\$-\$R\$m\$G\$9e(B

In message “Re: [ruby-dev:31760] Re: optimize range space”
on Sat, 8 Sep 2007 11:43:52 +0900, Tanaka A. [email protected]
writes:

|In article [email protected],
| Tanaka A. [email protected] writes:
|
|> Range e\$B\$N%a%b%j>CHq\$r@aLs\$9\$k\$N\$O\$I\$&\$G\$7\$g\$&\$+!#e(B
|
|e\$B\$I\$N\$/\$i\$\$@aLs\$G\$-\$k\$N\$+B,\$C\$F\$\$^\$7\$?!#e(B
|
|e\$B@aLs\$9\$kA0\$O!“0J2<\$N\$h\$&\$K!“e(B1000000e\$B8D\$Ne(B range e\$B\$r@8@.\$9\$k\$He(B
|106Mbytes e\$B\$[\$II,MW\$G\$9!#e(B
|
|% time ./ruby -e 'a = []; 1000000.times {|i| a << (i…i) }
|VmPeak: 105604 kB
|VmSize: 105604 kB
|VmLck: 0 kB
|VmHWM: 102596 kB
|VmData: 102772 kB
|VmStk: 84 kB
|VmExe: 1176 kB
|VmLib: 1492 kB
|VmPTE: 116 kB
|./ruby -e 7.61s user 0.20s system 98% cpu 7.952 total
|
|e\$B@aLs\$9\$k\$H!"0J2<\$N\$h\$&\$K!"e(B 35Mbytes e\$B\$[\$I\$G:Q\$
\$^\$9!#e(B
|
|% time ./ruby -e ‘a = []; 1000000.times {|i| a << (i…i) }
|VmPeak: 35416 kB
|VmSize: 35416 kB
|VmLck: 0 kB
|VmHWM: 32424 kB
|VmData: 32588 kB
|VmStk: 84 kB
|VmExe: 1176 kB
|VmLib: 1492 kB
|VmPTE: 48 kB
|./ruby -e 3.18s user 0.06s system 97% cpu 3.332 total
|
|e\$B\$D\$^\$j!";HMQ%a%b%j\$OH>J,0J2<\$K\$J\$j!“3d9g\$H\$7\$F\$OLse(B 6e\$B3d:o8:\$Ge(B
|e\$B\$-\$F\$\$\$^\$9!#e(B
|
|e\$B\$5\$i\$K!”\$+\$+\$C\$?;~4V\$b!“e(B8e\$BIC\$+\$ie(B 3.3e\$BIC\$/\$i\$\$\$H8:\$j!“G\0J>e\$Ke(B
|e\$B9bB.2=\$7\$F\$\$\$^\$9!#e(B
|
|e\$B\$3\$&\$7\$F\$_\$k\$H!”\$\$\$^\$Ne(B Range e\$B\$,\$\$\$+\$KL5BL\$J\$3\$H\$r\$7\$F\$\$\$k\$+e(B
|e\$B\$H\$\$\$&\$N\$,\$o\$+\$k\$N\$G\$9\$,!”\$\$\$+\$,\$G\$7\$g\$&\$+!#e(B

e\$B?t;z\$,\$"\$k\$H@bF@NO\$,A}\$7\$^\$9\$M!#%3%_%C%H\$7\$F\$/\$@\$5\$\$!#e(B