aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-01-30 20:40:18 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-01-30 20:40:18 +0000
commitb9f877bca0d52b52decca9b44870d6bfa03a994c (patch)
tree7d3adc431d4d4e83794b8bcdc769953d74137343 /io.c
parent7cda75d77941305294873d562721e28a4d67ff5a (diff)
downloadruby-b9f877bca0d52b52decca9b44870d6bfa03a994c.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.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/io.c b/io.c
index 322aabedc5..d03519be92 100644
--- a/io.c
+++ b/io.c
@@ -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