Implement Write Barriers on IO::Buffer
Benchmark: ``` require "benchmark" puts(Benchmark.measure do ary = 1_000_000.times.map { IO::Buffer.for("") } 10.times { GC.start(full_mark: false) } end) ``` Before: ``` 14.330119 0.051497 14.381616 ( 14.445106) ``` After: ``` 7.481152 0.040166 7.521318 ( 7.535209) ```
This commit is contained in:
parent
157e6c8a51
commit
c5e3d6da9c
32
io_buffer.c
32
io_buffer.c
@ -183,7 +183,7 @@ io_buffer_zero(struct rb_io_buffer *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
io_buffer_initialize(struct rb_io_buffer *buffer, void *base, size_t size, enum rb_io_buffer_flags flags, VALUE source)
|
io_buffer_initialize(VALUE self, struct rb_io_buffer *buffer, void *base, size_t size, enum rb_io_buffer_flags flags, VALUE source)
|
||||||
{
|
{
|
||||||
if (base) {
|
if (base) {
|
||||||
// If we are provided a pointer, we use it.
|
// If we are provided a pointer, we use it.
|
||||||
@ -209,7 +209,7 @@ io_buffer_initialize(struct rb_io_buffer *buffer, void *base, size_t size, enum
|
|||||||
buffer->base = base;
|
buffer->base = base;
|
||||||
buffer->size = size;
|
buffer->size = size;
|
||||||
buffer->flags = flags;
|
buffer->flags = flags;
|
||||||
buffer->source = source;
|
RB_OBJ_WRITE(self, &buffer->source, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -286,7 +286,7 @@ static const rb_data_type_t rb_io_buffer_type = {
|
|||||||
.dsize = rb_io_buffer_type_size,
|
.dsize = rb_io_buffer_type_size,
|
||||||
},
|
},
|
||||||
.data = NULL,
|
.data = NULL,
|
||||||
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract an offset argument, which must be a positive integer.
|
// Extract an offset argument, which must be a positive integer.
|
||||||
@ -420,7 +420,7 @@ static VALUE io_buffer_for_make_instance(VALUE klass, VALUE string, enum rb_io_b
|
|||||||
if (!(flags & RB_IO_BUFFER_READONLY))
|
if (!(flags & RB_IO_BUFFER_READONLY))
|
||||||
rb_str_modify(string);
|
rb_str_modify(string);
|
||||||
|
|
||||||
io_buffer_initialize(buffer, RSTRING_PTR(string), RSTRING_LEN(string), flags, string);
|
io_buffer_initialize(instance, buffer, RSTRING_PTR(string), RSTRING_LEN(string), flags, string);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -555,7 +555,7 @@ rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags)
|
|||||||
struct rb_io_buffer *buffer = NULL;
|
struct rb_io_buffer *buffer = NULL;
|
||||||
TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, buffer);
|
TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, buffer);
|
||||||
|
|
||||||
io_buffer_initialize(buffer, base, size, flags, Qnil);
|
io_buffer_initialize(instance, buffer, base, size, flags, Qnil);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -720,7 +720,7 @@ rb_io_buffer_initialize(int argc, VALUE *argv, VALUE self)
|
|||||||
flags |= io_flags_for_size(size);
|
flags |= io_flags_for_size(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
io_buffer_initialize(buffer, NULL, size, flags, Qnil);
|
io_buffer_initialize(self, buffer, NULL, size, flags, Qnil);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -1278,10 +1278,12 @@ rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_
|
|||||||
slice->size = length;
|
slice->size = length;
|
||||||
|
|
||||||
// The source should be the root buffer:
|
// The source should be the root buffer:
|
||||||
if (buffer->source != Qnil)
|
if (buffer->source != Qnil) {
|
||||||
slice->source = buffer->source;
|
RB_OBJ_WRITE(instance, &slice->source, buffer->source);
|
||||||
else
|
}
|
||||||
slice->source = self;
|
else {
|
||||||
|
RB_OBJ_WRITE(instance, &slice->source, self);
|
||||||
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -1478,11 +1480,11 @@ io_buffer_resize_clear(struct rb_io_buffer *buffer, void* base, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
io_buffer_resize_copy(struct rb_io_buffer *buffer, size_t size)
|
io_buffer_resize_copy(VALUE self, struct rb_io_buffer *buffer, size_t size)
|
||||||
{
|
{
|
||||||
// Slow path:
|
// Slow path:
|
||||||
struct rb_io_buffer resized;
|
struct rb_io_buffer resized;
|
||||||
io_buffer_initialize(&resized, NULL, size, io_flags_for_size(size), Qnil);
|
io_buffer_initialize(self, &resized, NULL, size, io_flags_for_size(size), Qnil);
|
||||||
|
|
||||||
if (buffer->base) {
|
if (buffer->base) {
|
||||||
size_t preserve = buffer->size;
|
size_t preserve = buffer->size;
|
||||||
@ -1507,7 +1509,7 @@ rb_io_buffer_resize(VALUE self, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buffer->base == NULL) {
|
if (buffer->base == NULL) {
|
||||||
io_buffer_initialize(buffer, NULL, size, io_flags_for_size(size), Qnil);
|
io_buffer_initialize(self, buffer, NULL, size, io_flags_for_size(size), Qnil);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1552,7 +1554,7 @@ rb_io_buffer_resize(VALUE self, size_t size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
io_buffer_resize_copy(buffer, size);
|
io_buffer_resize_copy(self, buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2247,7 +2249,7 @@ rb_io_buffer_initialize_copy(VALUE self, VALUE source)
|
|||||||
|
|
||||||
rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size);
|
rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size);
|
||||||
|
|
||||||
io_buffer_initialize(buffer, NULL, source_size, io_flags_for_size(source_size), Qnil);
|
io_buffer_initialize(self, buffer, NULL, source_size, io_flags_for_size(source_size), Qnil);
|
||||||
|
|
||||||
return io_buffer_copy_from(buffer, source_base, source_size, 0, NULL);
|
return io_buffer_copy_from(buffer, source_base, source_size, 0, NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user