зеркало из https://github.com/github/ruby.git
Implement Struct on VWA
The benchmark results show that this feature has either a positive or no impact on performance. The memory usage is also mostly unchanged, except in hexapdf, where there is a decrease in RSS. -------------- ----------- ---------- --------- ----------- ---------- --------- -------------- ------------- bench master (ms) stddev (%) RSS (MiB) branch (ms) stddev (%) RSS (MiB) branch 1st itr master/branch activerecord 70.8 2.2 56.0 71.7 2.2 56.0 0.99 0.99 erubi_rails 20.5 13.6 94.7 20.5 14.3 94.2 0.93 1.00 hexapdf 2541.0 0.7 212.8 2544.4 0.7 203.4 1.00 1.00 liquid-c 65.6 0.3 38.9 65.3 0.3 38.9 1.01 1.01 liquid-compile 63.7 0.3 34.6 61.1 0.2 34.6 1.04 1.04 liquid-render 163.1 0.1 37.1 163.3 0.1 37.1 1.00 1.00 mail 139.3 0.1 50.5 137.0 0.1 50.1 0.99 1.02 psych-load 2065.7 0.1 36.9 2068.2 0.1 37.3 1.00 1.00 railsbench 2034.6 0.5 103.9 2031.9 0.5 103.8 1.02 1.00 ruby-lsp 65.3 3.1 89.8 66.2 3.0 89.7 1.01 0.99 sequel 73.2 1.0 40.3 73.4 1.0 40.3 1.00 1.00 -------------- ----------- ---------- --------- ----------- ---------- --------- -------------- -------------
This commit is contained in:
Родитель
45ff2f4a89
Коммит
2543a6573f
|
@ -24,13 +24,13 @@ RANGE_BEG(VALUE r)
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
RANGE_END(VALUE r)
|
RANGE_END(VALUE r)
|
||||||
{
|
{
|
||||||
return RSTRUCT(r)->as.ary[1];
|
return RSTRUCT_GET(r, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
RANGE_EXCL(VALUE r)
|
RANGE_EXCL(VALUE r)
|
||||||
{
|
{
|
||||||
return RSTRUCT(r)->as.ary[2];
|
return RSTRUCT_GET(r, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
#include "ruby/ruby.h" /* for struct RBasic */
|
#include "ruby/ruby.h" /* for struct RBasic */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RSTRUCT_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX,
|
RSTRUCT_EMBED_LEN_MASK = RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 |
|
||||||
RSTRUCT_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER1),
|
RUBY_FL_USER3 | RUBY_FL_USER2 | RUBY_FL_USER1,
|
||||||
RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
|
RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
|
||||||
RSTRUCT_TRANSIENT_FLAG = FL_USER3,
|
RSTRUCT_TRANSIENT_FLAG = RUBY_FL_USER8,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RStruct {
|
struct RStruct {
|
||||||
|
@ -25,7 +25,12 @@ struct RStruct {
|
||||||
long len;
|
long len;
|
||||||
const VALUE *ptr;
|
const VALUE *ptr;
|
||||||
} heap;
|
} heap;
|
||||||
const VALUE ary[RSTRUCT_EMBED_LEN_MAX];
|
/* This is a length 1 array because:
|
||||||
|
* 1. GCC has a bug that does not optimize C flexible array members
|
||||||
|
* (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452)
|
||||||
|
* 2. Zero length arrays are not supported by all compilers
|
||||||
|
*/
|
||||||
|
const VALUE ary[1];
|
||||||
} as;
|
} as;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -145,7 +150,7 @@ RSTRUCT_GET(VALUE st, long k)
|
||||||
static inline const VALUE *
|
static inline const VALUE *
|
||||||
rb_struct_const_heap_ptr(VALUE st)
|
rb_struct_const_heap_ptr(VALUE st)
|
||||||
{
|
{
|
||||||
/* TODO: check embed on debug mode */
|
assert(!FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK));
|
||||||
return RSTRUCT(st)->as.heap.ptr;
|
return RSTRUCT(st)->as.heap.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
struct.c
21
struct.c
|
@ -835,23 +835,28 @@ rb_struct_transient_heap_evacuate(VALUE obj, int promote)
|
||||||
static VALUE
|
static VALUE
|
||||||
struct_alloc(VALUE klass)
|
struct_alloc(VALUE klass)
|
||||||
{
|
{
|
||||||
long n;
|
long n = num_members(klass);
|
||||||
NEWOBJ_OF(st, struct RStruct, klass, T_STRUCT | (RGENGC_WB_PROTECTED_STRUCT ? FL_WB_PROTECTED : 0), sizeof(struct RStruct), 0);
|
size_t embedded_size = offsetof(struct RStruct, as.ary) + (sizeof(VALUE) * n);
|
||||||
|
VALUE flags = T_STRUCT | (RGENGC_WB_PROTECTED_STRUCT ? FL_WB_PROTECTED : 0);
|
||||||
|
|
||||||
n = num_members(klass);
|
if (n > 0 && rb_gc_size_allocatable_p(embedded_size)) {
|
||||||
|
flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
|
||||||
|
|
||||||
|
NEWOBJ_OF(st, struct RStruct, klass, flags, embedded_size, 0);
|
||||||
|
|
||||||
if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
|
|
||||||
RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
|
|
||||||
RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
|
|
||||||
rb_mem_clear((VALUE *)st->as.ary, n);
|
rb_mem_clear((VALUE *)st->as.ary, n);
|
||||||
|
|
||||||
|
return (VALUE)st;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
NEWOBJ_OF(st, struct RStruct, klass, flags, embedded_size, 0);
|
||||||
|
|
||||||
st->as.heap.ptr = struct_heap_alloc((VALUE)st, n);
|
st->as.heap.ptr = struct_heap_alloc((VALUE)st, n);
|
||||||
rb_mem_clear((VALUE *)st->as.heap.ptr, n);
|
rb_mem_clear((VALUE *)st->as.heap.ptr, n);
|
||||||
st->as.heap.len = n;
|
st->as.heap.len = n;
|
||||||
}
|
|
||||||
|
|
||||||
return (VALUE)st;
|
return (VALUE)st;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
|
|
|
@ -695,7 +695,7 @@ mod manual_defs {
|
||||||
pub const VM_CALL_OPT_SEND : u32 = 1 << VM_CALL_OPT_SEND_bit;
|
pub const VM_CALL_OPT_SEND : u32 = 1 << VM_CALL_OPT_SEND_bit;
|
||||||
|
|
||||||
// From internal/struct.h - in anonymous enum, so we can't easily import it
|
// From internal/struct.h - in anonymous enum, so we can't easily import it
|
||||||
pub const RSTRUCT_EMBED_LEN_MASK: usize = (RUBY_FL_USER2 | RUBY_FL_USER1) as usize;
|
pub const RSTRUCT_EMBED_LEN_MASK: usize = (RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3 |RUBY_FL_USER2 | RUBY_FL_USER1) as usize;
|
||||||
|
|
||||||
// From iseq.h - via a different constant, which seems to confuse bindgen
|
// From iseq.h - via a different constant, which seems to confuse bindgen
|
||||||
pub const ISEQ_TRANSLATED: usize = RUBY_FL_USER7 as usize;
|
pub const ISEQ_TRANSLATED: usize = RUBY_FL_USER7 as usize;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче