dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH] file.c: avoid on-stack stat buffer copy
@ 2017-03-24 18:44 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2017-03-24 18:44 UTC (permalink / raw)
  To: spew

Optimize the successful case of File.stat, File.lstat, IO#stat,
File#lstat by avoiding copying of "struct stat" from the stack
to heap memory.

The exception case is slower, but exceptions ought to be rare
and not worth optimizing

* file.c (stat_wrap): new function
  (stat_fail): ditto
  (rb_file_s_stat): optimize for success, avoid on-stack "struct stat"
  (rb_io_stat): ditto
  (rb_file_s_lstat): ditto
  (rb_file_lstat): ditto
---
 file.c | 54 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 16 deletions(-)

diff --git a/file.c b/file.c
index c576c85c0a..2e13383f9c 100644
--- a/file.c
+++ b/file.c
@@ -429,6 +429,12 @@ get_stat(VALUE self)
     return st;
 }
 
+static VALUE
+stat_wrap(struct stat *st)
+{
+    return TypedData_Wrap_Struct(rb_cStat, &stat_data_type, st);
+}
+
 static struct timespec stat_mtimespec(struct stat *st);
 
 /*
@@ -1084,6 +1090,16 @@ call_w32_io_info(VALUE arg)
 }
 #endif
 
+static void
+stat_fail(struct stat *st, VALUE fname)
+{
+    int err = errno;
+
+    xfree(st);
+    errno = err;
+    rb_sys_fail_path(fname);
+}
+
 /*
  *  call-seq:
  *     File.stat(file_name)   ->  stat
@@ -1098,13 +1114,14 @@ call_w32_io_info(VALUE arg)
 static VALUE
 rb_file_s_stat(VALUE klass, VALUE fname)
 {
-    struct stat st;
+    struct stat *st;
 
     FilePathValue(fname);
-    if (rb_stat(fname, &st) < 0) {
-	rb_sys_fail_path(fname);
+    st = ALLOC(struct stat);
+    if (rb_stat(fname, st) < 0) {
+	stat_fail(st, fname);
     }
-    return rb_stat_new(&st);
+    return stat_wrap(st);
 }
 
 /*
@@ -1126,13 +1143,14 @@ static VALUE
 rb_io_stat(VALUE obj)
 {
     rb_io_t *fptr;
-    struct stat st;
+    struct stat *st;
 
     GetOpenFile(obj, fptr);
-    if (fstat(fptr->fd, &st) == -1) {
-	rb_sys_fail_path(fptr->pathv);
+    st = ALLOC(struct stat);
+    if (fstat(fptr->fd, st) == -1) {
+	stat_fail(st, fptr->pathv);
     }
-    return rb_stat_new(&st);
+    return stat_wrap(st);
 }
 
 /*
@@ -1153,14 +1171,17 @@ static VALUE
 rb_file_s_lstat(VALUE klass, VALUE fname)
 {
 #ifdef HAVE_LSTAT
-    struct stat st;
+    struct stat *st;
+    const char *cstr;
 
     FilePathValue(fname);
     fname = rb_str_encode_ospath(fname);
-    if (lstat(StringValueCStr(fname), &st) == -1) {
-	rb_sys_fail_path(fname);
+    cstr = StringValueCStr(fname);
+    st = ALLOC(struct stat);
+    if (lstat(cstr, st) == -1) {
+	stat_fail(st, fname);
     }
-    return rb_stat_new(&st);
+    return stat_wrap(st);
 #else
     return rb_file_s_stat(klass, fname);
 #endif
@@ -1185,16 +1206,17 @@ rb_file_lstat(VALUE obj)
 {
 #ifdef HAVE_LSTAT
     rb_io_t *fptr;
-    struct stat st;
+    struct stat *st;
     VALUE path;
 
     GetOpenFile(obj, fptr);
     if (NIL_P(fptr->pathv)) return Qnil;
     path = rb_str_encode_ospath(fptr->pathv);
-    if (lstat(RSTRING_PTR(path), &st) == -1) {
-	rb_sys_fail_path(fptr->pathv);
+    st = ALLOC(struct stat);
+    if (lstat(RSTRING_PTR(path), st) == -1) {
+	stat_fail(st, fptr->pathv);
     }
-    return rb_stat_new(&st);
+    return stat_wrap(st);
 #else
     return rb_io_stat(obj);
 #endif
-- 
EW


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2017-03-24 18:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-24 18:44 [PATCH] file.c: avoid on-stack stat buffer copy Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).