diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-01-30 20:40:18 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-01-30 20:40:18 +0000 |
commit | 9c4ba969a567450bee08211cc3ed1d2fa4655831 (patch) | |
tree | 7d3adc431d4d4e83794b8bcdc769953d74137343 /io.c | |
parent | 886e8f75caa5428b5eaf76ce80a74d89380b1aca (diff) | |
download | ruby-9c4ba969a567450bee08211cc3ed1d2fa4655831.tar.gz |
io.c: recycle garbage on write
* string.c (STR_IS_SHARED_M): new flag to mark shared mulitple times
(STR_SET_SHARED): set STR_IS_SHARED_M
(rb_str_tmp_frozen_acquire, rb_str_tmp_frozen_release): new functions
(str_new_frozen): set/unset STR_IS_SHARED_M as appropriate
* internal.h: declare new functions
* io.c (fwrite_arg, fwrite_do, fwrite_end): new
(io_fwrite): use new functions
Introduce rb_str_tmp_frozen_acquire and rb_str_tmp_frozen_release
to manage a hidden, frozen string. Reuse one bit of the embed
length for shared strings as STR_IS_SHARED_M to indicate a string
has been shared multiple times. In the common case, the string
is only shared once so the object slot can be reclaimed immediately.
minimum results in each 3 measurements. (time and size)
Execution time (sec)
name trunk built
io_copy_stream_write 0.682 0.254
io_copy_stream_write_socket 1.225 0.751
Speedup ratio: compare with the result of `trunk' (greater is better)
name built
io_copy_stream_write 2.680
io_copy_stream_write_socket 1.630
Memory usage (last size) (B)
name trunk built
io_copy_stream_write 95436800.000 6512640.000
io_copy_stream_write_socket 117628928.000 7127040.000
Memory consuming ratio (size) with the result of `trunk' (greater is better)
name built
io_copy_stream_write 14.654
io_copy_stream_write_socket 16.505
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57469 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r-- | io.c | 40 |
1 files changed, 36 insertions, 4 deletions
@@ -1419,10 +1419,40 @@ do_writeconv(VALUE str, rb_io_t *fptr, int *converted) return str; } +struct fwrite_arg { + VALUE orig; + VALUE tmp; + rb_io_t *fptr; + int nosync; +}; + +static VALUE +fwrite_do(VALUE arg) +{ + struct fwrite_arg *fa = (struct fwrite_arg *)arg; + const char *ptr; + long len; + + RSTRING_GETMEM(fa->tmp, ptr, len); + + return (VALUE)io_binwrite(fa->tmp, ptr, len, fa->fptr, fa->nosync); +} + +static VALUE +fwrite_end(VALUE arg) +{ + struct fwrite_arg *fa = (struct fwrite_arg *)arg; + + rb_str_tmp_frozen_release(fa->orig, fa->tmp); + + return Qfalse; +} + static long io_fwrite(VALUE str, rb_io_t *fptr, int nosync) { int converted = 0; + struct fwrite_arg fa; #ifdef _WIN32 if (fptr->mode & FMODE_TTY) { long len = rb_w32_write_console(str, fptr->fd); @@ -1432,11 +1462,13 @@ io_fwrite(VALUE str, rb_io_t *fptr, int nosync) str = do_writeconv(str, fptr, &converted); if (converted) OBJ_FREEZE(str); - else - str = rb_str_new_frozen(str); - return io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), - fptr, nosync); + fa.orig = str; + fa.tmp = rb_str_tmp_frozen_acquire(str); + fa.fptr = fptr; + fa.nosync = nosync; + + return (long)rb_ensure(fwrite_do, (VALUE)&fa, fwrite_end, (VALUE)&fa); } ssize_t |