* [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).