dumping ground for random patches and texts
 help / color / mirror / Atom feed
From: Eric Wong <e@80x24.org>
To: spew@80x24.org
Subject: [PATCH] file.c: avoid on-stack stat buffer copy
Date: Fri, 24 Mar 2017 18:44:01 +0000	[thread overview]
Message-ID: <20170324184401.29511-1-e@80x24.org> (raw)

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


                 reply	other threads:[~2017-03-24 18:44 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170324184401.29511-1-e@80x24.org \
    --to=e@80x24.org \
    --cc=spew@80x24.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).