Embed small size array elements in the heap.

It reduces the memory consumption and sometimes improve the
performance as well.  For example, the consumed memory size
of `bench/bm_ao_render.rb` is reduced from 1.2GB to 1GB, and
its total execution time become 18.795 sec from 22.229 sec.
parent 5d44f858
......@@ -21,22 +21,48 @@ typedef struct mrb_shared_array {
mrb_value *ptr;
} mrb_shared_array;
#define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value)))
struct RArray {
MRB_OBJECT_HEADER;
mrb_int len;
union {
mrb_int capa;
mrb_shared_array *shared;
} aux;
mrb_value *ptr;
struct {
mrb_int len;
union {
mrb_int capa;
mrb_shared_array *shared;
} aux;
mrb_value *ptr;
} heap;
mrb_value embed[MRB_ARY_EMBED_LEN_MAX];
} as;
};
#define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v)))
#define mrb_ary_value(p) mrb_obj_value((void*)(p))
#define RARRAY(v) ((struct RArray*)(mrb_ptr(v)))
#define RARRAY_LEN(a) (RARRAY(a)->len)
#define RARRAY_PTR(a) ((const mrb_value*)RARRAY(a)->ptr)
#define MRB_ARY_EMBED 4
#define MRB_ARY_EMBED_MASK 3
#define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED)
#define ARY_SET_EMBED_FLAG(a) ((a)->flags |= MRB_ARY_EMBED)
#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED|MRB_ARY_EMBED_MASK))
#define ARY_EMBED_LEN(a) ((a)->flags & MRB_ARY_EMBED_MASK)
#define ARY_SET_EMBED_LEN(a,len) (a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((len)&MRB_ARY_EMBED_MASK);
#define ARY_EMBED_PTR(a) (&((a)->as.embed[0]))
#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
#define RARRAY_LEN(a) ARY_LEN(RARRAY(a))
#define RARRAY_PTR(a) ARY_PTR(RARRAY(a))
#define ARY_SET_LEN(a,n) do {\
if (ARY_EMBED_P(a)) {\
mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \
ARY_SET_EMBED_LEN(a,n);\
}\
else\
(a)->as.heap.len = (n);\
} while (0)
#define ARY_CAPA(a) (ARY_EMBED_P(a)?MRB_ARY_EMBED_LEN_MAX:(a)->as.heap.aux.capa)
#define MRB_ARY_SHARED 256
#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED)
#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
......
......@@ -174,7 +174,7 @@ static mrb_value
mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
mrb_int i, j, k, len;
mrb_int i, j, k, len, alen = ARY_LEN(a);
mrb_value index;
mrb_value val;
mrb_value *ptr;
......@@ -185,7 +185,7 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
switch (mrb_type(index)) {
case MRB_TT_RANGE:
if (mrb_range_beg_len(mrb, index, &i, &len, a->len, TRUE) == 1) {
if (mrb_range_beg_len(mrb, index, &i, &len, alen, TRUE) == 1) {
goto delete_pos_len;
}
else {
......@@ -202,25 +202,25 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
i = mrb_fixnum(index);
delete_pos_len:
if (i < 0) i += a->len;
if (i < 0 || a->len < i) return mrb_nil_value();
if (i < 0) i += alen;
if (i < 0 || alen < i) return mrb_nil_value();
if (len < 0) return mrb_nil_value();
if (a->len == i) return mrb_ary_new(mrb);
if (len > a->len - i) len = a->len - i;
if (alen == i) return mrb_ary_new(mrb);
if (len > alen - i) len = alen - i;
ary = mrb_ary_new_capa(mrb, len);
ptr = ARY_PTR(a);
for (j = i, k = 0; k < len; ++j, ++k) {
mrb_ary_push(mrb, ary, a->ptr[j]);
mrb_ary_push(mrb, ary, ptr[j]);
}
ptr = a->ptr + i;
for (j = i; j < a->len - len; ++j) {
ptr += i;
for (j = i; j < alen - len; ++j) {
*ptr = *(ptr+len);
++ptr;
}
mrb_ary_resize(mrb, self, a->len - len);
mrb_ary_resize(mrb, self, alen - len);
return ary;
}
......
......@@ -217,13 +217,15 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary)
for (i = RARRAY_LEN(ary) - 1; i > 0; i--) {
mrb_int j;
mrb_value *ptr = RARRAY_PTR(ary);
mrb_value tmp;
j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary))));
tmp = RARRAY_PTR(ary)[i];
mrb_ary_ptr(ary)->ptr[i] = RARRAY_PTR(ary)[j];
mrb_ary_ptr(ary)->ptr[j] = tmp;
tmp = ptr[i];
ptr[i] = ptr[j];
ptr[j] = tmp;
}
}
......
......@@ -13,8 +13,8 @@
#include <mruby/hash.h>
#include <mruby/range.h>
#define RSTRUCT_LEN(st) mrb_ary_ptr(st)->len
#define RSTRUCT_PTR(st) mrb_ary_ptr(st)->ptr
#define RSTRUCT_LEN(st) RARRAY_LEN(st)
#define RSTRUCT_PTR(st) RARRAY_PTR(st)
static struct RClass *
struct_class(mrb_state *mrb)
......
This diff is collapsed.
......@@ -564,7 +564,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
va_list ap;
int argc = mrb->c->ci->argc;
int arg_i = 0;
mrb_bool array_argv;
mrb_value *array_argv;
mrb_bool opt = FALSE;
mrb_bool given = TRUE;
......@@ -572,15 +572,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (argc < 0) {
struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]);
argc = a->len;
array_argv = TRUE;
argc = ARY_LEN(a);
array_argv = ARY_PTR(a);
}
else {
array_argv = FALSE;
array_argv = NULL;
}
#define ARGV \
(array_argv ? mrb_ary_ptr(mrb->c->stack[1])->ptr : (mrb->c->stack + 1))
(array_argv ? array_argv : (mrb->c->stack + 1))
while ((c = *format++)) {
switch (c) {
......@@ -751,8 +751,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (i < argc) {
aa = to_ary(mrb, ARGV[arg_i++]);
a = mrb_ary_ptr(aa);
*pb = a->ptr;
*pl = a->len;
*pb = ARY_PTR(a);
*pl = ARY_LEN(a);
i++;
}
}
......@@ -896,7 +896,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_value **var;
mrb_int *pl;
mrb_bool nocopy = FALSE;
mrb_bool nocopy = array_argv ? TRUE : FALSE;
if (*format == '!') {
format++;
......@@ -913,7 +913,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
else {
mrb_value args = mrb_ary_new_from_values(mrb, *pl, ARGV+arg_i);
RARRAY(args)->c = NULL;
*var = (mrb_value*)RARRAY_PTR(args);
*var = RARRAY_PTR(args);
}
}
i = argc;
......
......@@ -466,10 +466,13 @@ mrb_gc_unregister(mrb_state *mrb, mrb_value obj)
}
a = mrb_ary_ptr(table);
mrb_ary_modify(mrb, a);
for (i = 0; i < a->len; i++) {
if (mrb_obj_eq(mrb, a->ptr[i], obj)) {
a->len--;
memmove(&a->ptr[i], &a->ptr[i + 1], (a->len - i) * sizeof(a->ptr[i]));
for (i = 0; i < ARY_LEN(a); i++) {
if (mrb_obj_eq(mrb, ARY_PTR(a)[i], obj)) {
mrb_int len = ARY_LEN(a)-1;
mrb_value *ptr = ARY_PTR(a);
ARY_SET_LEN(a, len);
memmove(&ptr[i], &ptr[i + 1], (len - i) * sizeof(mrb_value));
break;
}
}
......@@ -678,8 +681,8 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
struct RArray *a = (struct RArray*)obj;
size_t i, e;
for (i=0,e=a->len; i<e; i++) {
mrb_gc_mark_value(mrb, a->ptr[i]);
for (i=0,e=ARY_LEN(a); i<e; i++) {
mrb_gc_mark_value(mrb, ARY_PTR(a)[i]);
}
}
break;
......@@ -790,9 +793,9 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
case MRB_TT_ARRAY:
if (ARY_SHARED_P(obj))
mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared);
else
mrb_free(mrb, ((struct RArray*)obj)->ptr);
mrb_ary_decref(mrb, ((struct RArray*)obj)->as.heap.aux.shared);
else if (!ARY_EMBED_P(obj))
mrb_free(mrb, ((struct RArray*)obj)->as.heap.ptr);
break;
case MRB_TT_HASH:
......@@ -950,7 +953,7 @@ gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
case MRB_TT_ARRAY:
{
struct RArray *a = (struct RArray*)obj;
children += a->len;
children += ARY_LEN(a);
}
break;
......
......@@ -759,7 +759,7 @@ mrb_hash_keys(mrb_state *mrb, mrb_value hash)
ary = mrb_ary_new_capa(mrb, kh_size(h));
end = kh_size(h)-1;
mrb_ary_set(mrb, ary, end, mrb_nil_value());
p = mrb_ary_ptr(ary)->ptr;
p = RARRAY_PTR(ary);
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) {
mrb_value kv = kh_key(h, k);
......
......@@ -1717,21 +1717,21 @@ RETRY_TRY_BLOCK:
if (mrb_array_p(stack[m1])) {
struct RArray *ary = mrb_ary_ptr(stack[m1]);
pp = ary->ptr;
len = ary->len;
pp = ARY_PTR(ary);
len = ARY_LEN(ary);
}
regs[a] = mrb_ary_new_capa(mrb, m1+len+m2);
rest = mrb_ary_ptr(regs[a]);
if (m1 > 0) {
stack_copy(rest->ptr, stack, m1);
stack_copy(ARY_PTR(rest), stack, m1);
}
if (len > 0) {
stack_copy(rest->ptr+m1, pp, len);
stack_copy(ARY_PTR(rest)+m1, pp, len);
}
if (m2 > 0) {
stack_copy(rest->ptr+m1+len, stack+m1+1, m2);
stack_copy(ARY_PTR(rest)+m1+len, stack+m1+1, m2);
}
rest->len = m1+len+m2;
ARY_SET_LEN(rest, m1+len+m2);
}
regs[a+1] = stack[m1+r+m2];
mrb_gc_arena_restore(mrb, ai);
......@@ -1759,8 +1759,8 @@ RETRY_TRY_BLOCK:
if (argc < 0) {
struct RArray *ary = mrb_ary_ptr(regs[1]);
argv = ary->ptr;
argc = ary->len;
argv = ARY_PTR(ary);
argc = ARY_LEN(ary);
mrb_gc_protect(mrb, regs[1]);
}
if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) {
......@@ -1773,8 +1773,8 @@ RETRY_TRY_BLOCK:
}
else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
mrb_gc_protect(mrb, argv[0]);
argc = mrb_ary_ptr(argv[0])->len;
argv = mrb_ary_ptr(argv[0])->ptr;
argc = RARRAY_LEN(argv[0]);
argv = RARRAY_PTR(argv[0]);
}
if (argc < len) {
int mlen = m2;
......@@ -2645,19 +2645,19 @@ RETRY_TRY_BLOCK:
v = mrb_ary_new_from_values(mrb, 1, &regs[a]);
}
ary = mrb_ary_ptr(v);
len = ary->len;
len = ARY_LEN(ary);
if (len > pre + post) {
v = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre);
v = mrb_ary_new_from_values(mrb, len - pre - post, ARY_PTR(ary)+pre);
regs[a++] = v;
while (post--) {
regs[a++] = ary->ptr[len-post-1];
regs[a++] = ARY_PTR(ary)[len-post-1];
}
}
else {
v = mrb_ary_new_capa(mrb, 0);
regs[a++] = v;
for (idx=0; idx+pre<len; idx++) {
regs[a+idx] = ary->ptr[pre+idx];
regs[a+idx] = ARY_PTR(ary)[pre+idx];
}
while (idx < post) {
SET_NIL_VALUE(regs[a+idx]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment