Allow io_buffer_memmove
to release the GVL for large buffers. (#12021)
[Feature #20902]
This commit is contained in:
parent
682ff52e8f
commit
3c0b09ac9e
Notes:
git
2024-11-20 08:27:36 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>
5
NEWS.md
5
NEWS.md
@ -66,6 +66,10 @@ Note: We're only listing outstanding class updates.
|
|||||||
* An optional `Fiber::Scheduler#blocking_operation_wait` hook allows blocking operations to be moved out of the
|
* An optional `Fiber::Scheduler#blocking_operation_wait` hook allows blocking operations to be moved out of the
|
||||||
event loop in order to reduce latency and improve multi-core processor utilization. [[Feature #20876]]
|
event loop in order to reduce latency and improve multi-core processor utilization. [[Feature #20876]]
|
||||||
|
|
||||||
|
* IO::Buffer
|
||||||
|
|
||||||
|
* `IO::Buffer#copy` can release the GVL, allowing other threads to run while copying data. [[Feature #20902]]
|
||||||
|
|
||||||
## Stdlib updates
|
## Stdlib updates
|
||||||
|
|
||||||
* Tempfile
|
* Tempfile
|
||||||
@ -242,3 +246,4 @@ details of the default gems or bundled gems.
|
|||||||
[Feature #20624]: https://bugs.ruby-lang.org/issues/20624
|
[Feature #20624]: https://bugs.ruby-lang.org/issues/20624
|
||||||
[Feature #20775]: https://bugs.ruby-lang.org/issues/20775
|
[Feature #20775]: https://bugs.ruby-lang.org/issues/20775
|
||||||
[Feature #20876]: https://bugs.ruby-lang.org/issues/20876
|
[Feature #20876]: https://bugs.ruby-lang.org/issues/20876
|
||||||
|
[Feature #20902]: https://bugs.ruby-lang.org/issues/20902
|
||||||
|
@ -8816,6 +8816,7 @@ io_buffer.$(OBJEXT): {$(VPATH)}onigmo.h
|
|||||||
io_buffer.$(OBJEXT): {$(VPATH)}oniguruma.h
|
io_buffer.$(OBJEXT): {$(VPATH)}oniguruma.h
|
||||||
io_buffer.$(OBJEXT): {$(VPATH)}st.h
|
io_buffer.$(OBJEXT): {$(VPATH)}st.h
|
||||||
io_buffer.$(OBJEXT): {$(VPATH)}subst.h
|
io_buffer.$(OBJEXT): {$(VPATH)}subst.h
|
||||||
|
io_buffer.$(OBJEXT): {$(VPATH)}thread.h
|
||||||
io_buffer.$(OBJEXT): {$(VPATH)}thread_native.h
|
io_buffer.$(OBJEXT): {$(VPATH)}thread_native.h
|
||||||
iseq.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
|
iseq.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
|
||||||
iseq.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
|
iseq.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
|
||||||
|
39
io_buffer.c
39
io_buffer.c
@ -9,6 +9,9 @@
|
|||||||
#include "ruby/io/buffer.h"
|
#include "ruby/io/buffer.h"
|
||||||
#include "ruby/fiber/scheduler.h"
|
#include "ruby/fiber/scheduler.h"
|
||||||
|
|
||||||
|
// For `rb_nogvl`.
|
||||||
|
#include "ruby/thread.h"
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "internal/array.h"
|
#include "internal/array.h"
|
||||||
#include "internal/bits.h"
|
#include "internal/bits.h"
|
||||||
@ -2327,6 +2330,30 @@ io_buffer_set_values(VALUE self, VALUE buffer_types, VALUE _offset, VALUE values
|
|||||||
return SIZET2NUM(offset);
|
return SIZET2NUM(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t IO_BUFFER_BLOCKING_SIZE = 1024*1024;
|
||||||
|
|
||||||
|
struct io_buffer_memmove_arguments {
|
||||||
|
unsigned char * destination;
|
||||||
|
const unsigned char * source;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
io_buffer_memmove_blocking(void *data)
|
||||||
|
{
|
||||||
|
struct io_buffer_memmove_arguments *arguments = (struct io_buffer_memmove_arguments *)data;
|
||||||
|
|
||||||
|
memmove(arguments->destination, arguments->source, arguments->length);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
io_buffer_memmove_unblock(void *data)
|
||||||
|
{
|
||||||
|
// No safe way to interrupt.
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
io_buffer_memmove(struct rb_io_buffer *buffer, size_t offset, const void *source_base, size_t source_offset, size_t source_size, size_t length)
|
io_buffer_memmove(struct rb_io_buffer *buffer, size_t offset, const void *source_base, size_t source_offset, size_t source_size, size_t length)
|
||||||
{
|
{
|
||||||
@ -2340,8 +2367,16 @@ io_buffer_memmove(struct rb_io_buffer *buffer, size_t offset, const void *source
|
|||||||
rb_raise(rb_eArgError, "The computed source range exceeds the size of the source buffer!");
|
rb_raise(rb_eArgError, "The computed source range exceeds the size of the source buffer!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length != 0) {
|
struct io_buffer_memmove_arguments arguments = {
|
||||||
memmove((unsigned char*)base+offset, (const unsigned char*)source_base+source_offset, length);
|
.destination = (unsigned char*)base+offset,
|
||||||
|
.source = (unsigned char*)source_base+source_offset,
|
||||||
|
.length = length
|
||||||
|
};
|
||||||
|
|
||||||
|
if (arguments.length >= IO_BUFFER_BLOCKING_SIZE) {
|
||||||
|
rb_nogvl(io_buffer_memmove_blocking, &arguments, io_buffer_memmove_unblock, &arguments, RB_NOGVL_OFFLOAD_SAFE);
|
||||||
|
} else if (arguments.length != 0) {
|
||||||
|
memmove(arguments.destination, arguments.source, arguments.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user