Skip to content

Commit 30faa4f

Browse files
committed
[GR-17457] Improve glob performance.
PullRequest: truffleruby/2661
2 parents ed30896 + 7e332ac commit 30faa4f

File tree

11 files changed

+340
-80
lines changed

11 files changed

+340
-80
lines changed

spec/ruby/core/dir/glob_spec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@
133133
Dir.glob('{deeply/**/,subdir_two/*}').sort.should == expected
134134
end
135135

136+
it "preserves multiple /s before a **" do
137+
expected = %w[
138+
deeply//nested/directory/structure
139+
]
140+
141+
Dir.glob('{deeply//**/structure}').sort.should == expected
142+
end
143+
136144
it "accepts a block and yields it with each elements" do
137145
ary = []
138146
ret = Dir.glob(["file_o*", "file_t*"]) { |t| ary << t }

src/main/c/truffleposix/truffleposix.c

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,39 @@ char* truffleposix_get_user_home(const char *name) {
229229
}
230230
}
231231

232-
char* truffleposix_readdir(DIR *dirp) {
232+
struct dirent *truffleposix_readdir(DIR *dirp) {
233233
errno = 0;
234234
struct dirent *entry = readdir(dirp);
235-
if (entry != NULL) {
235+
if (entry) {
236+
if (entry->d_type == DT_UNKNOWN) {
237+
struct stat native_stat;
238+
int result = fstatat(dirfd(dirp), entry->d_name, &native_stat, AT_SYMLINK_NOFOLLOW);
239+
if (result == 0) {
240+
if (S_ISREG(native_stat.st_mode)) {
241+
entry->d_type = DT_REG;
242+
} else if(S_ISDIR(native_stat.st_mode)) {
243+
entry->d_type = DT_DIR;
244+
} else if (S_ISCHR(native_stat.st_mode)) {
245+
entry->d_type = DT_CHR;;
246+
} else if (S_ISBLK(native_stat.st_mode)) {
247+
entry->d_type = DT_BLK;
248+
} else if (S_ISFIFO(native_stat.st_mode)) {
249+
entry->d_type = DT_FIFO;
250+
} else if (S_ISLNK(native_stat.st_mode)) {
251+
entry->d_type = DT_LNK;
252+
} else if (S_ISSOCK(native_stat.st_mode)) {
253+
entry->d_type = DT_SOCK;
254+
}
255+
}
256+
}
257+
}
258+
return entry;
259+
}
260+
261+
char *truffleposix_readdir_name(DIR *dirp) {
262+
errno = 0;
263+
struct dirent *entry = readdir(dirp);
264+
if (entry) {
236265
return entry->d_name;
237266
} else if (errno == 0) {
238267
return "";
@@ -371,6 +400,33 @@ int64_t truffleposix_fstat_size(int fd) {
371400
return result;
372401
}
373402

403+
int truffleposix_fstatat(int dirfd, char *path, struct truffleposix_stat *buffer, int flags) {
404+
struct stat native_stat;
405+
int result = fstatat(dirfd, path, &native_stat, flags);
406+
if (result == 0) {
407+
copy_stat(&native_stat, buffer);
408+
}
409+
return result;
410+
}
411+
412+
mode_t truffleposix_fstatat_mode(int dirfd, char *path, int flags) {
413+
struct stat native_stat;
414+
int result = fstatat(dirfd, path, &native_stat, flags);
415+
if (result == 0) {
416+
return native_stat.st_mode;
417+
}
418+
return 0;
419+
}
420+
421+
int64_t truffleposix_fstatat_size(int dirfd, char *path, int flags) {
422+
struct stat native_stat;
423+
int result = fstatat(dirfd, path, &native_stat, flags);
424+
if (result == 0) {
425+
return native_stat.st_size;
426+
}
427+
return result;
428+
}
429+
374430
int truffleposix_lstat(const char *path, struct truffleposix_stat *buffer) {
375431
struct stat native_stat;
376432
int result = lstat(path, &native_stat);

src/main/java/org/truffleruby/core/CoreLibrary.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,7 @@ public boolean isTruffleBootMainMethod(SharedMethodInfo info) {
10121012
"/core/errno.rb",
10131013
"/core/truffle/file_operations.rb",
10141014
"/core/file.rb",
1015+
"/core/truffle/dir_operations.rb",
10151016
"/core/dir.rb",
10161017
"/core/dir_glob.rb",
10171018
"/core/file_test.rb",

src/main/java/org/truffleruby/platform/DarwinAMD64NativeConfiguration.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ public static void load(NativeConfiguration configuration, RubyContext context)
4747
configuration.config("platform.sigaction.sa_handler.offset", 0);
4848
configuration.config("platform.sigaction.sa_handler.size", 8);
4949
configuration.config("platform.sigaction.sa_handler.type", string(context, "pointer"));
50+
configuration.config("platform.dirent.sizeof", 1048);
51+
configuration.config("platform.dirent.d_name.offset", 21);
52+
configuration.config("platform.dirent.d_name.size", 1024);
53+
configuration.config("platform.dirent.d_name.type", string(context, "char_array"));
54+
configuration.config("platform.dirent.d_type.offset", 20);
55+
configuration.config("platform.dirent.d_type.size", 1);
56+
configuration.config("platform.dirent.d_type.type", string(context, "uchar"));
5057
configuration.config("platform.addrinfo.sizeof", 48);
5158
configuration.config("platform.addrinfo.ai_flags.offset", 0);
5259
configuration.config("platform.addrinfo.ai_flags.size", 4);
@@ -353,6 +360,15 @@ public static void load(NativeConfiguration configuration, RubyContext context)
353360
configuration.config("platform.file.S_ISUID", 2048);
354361
configuration.config("platform.file.S_ISGID", 1024);
355362
configuration.config("platform.file.S_ISVTX", 512);
363+
configuration.config("platform.file.DT_BLK", 6);
364+
configuration.config("platform.file.DT_CHR", 2);
365+
configuration.config("platform.file.DT_DIR", 4);
366+
configuration.config("platform.file.DT_FIFO", 1);
367+
configuration.config("platform.file.DT_LNK", 10);
368+
configuration.config("platform.file.DT_REG", 8);
369+
configuration.config("platform.file.DT_SOCK", 12);
370+
configuration.config("platform.file.DT_UNKNOWN", 0);
371+
configuration.config("platform.file.AT_SYMLINK_NOFOLLOW", 32);
356372
configuration.config("platform.io.SEEK_SET", 0);
357373
configuration.config("platform.io.SEEK_CUR", 1);
358374
configuration.config("platform.io.SEEK_END", 2);

src/main/java/org/truffleruby/platform/LinuxAMD64NativeConfiguration.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ public static void load(NativeConfiguration configuration, RubyContext context)
4747
configuration.config("platform.sigaction.sa_handler.offset", 0);
4848
configuration.config("platform.sigaction.sa_handler.size", 8);
4949
configuration.config("platform.sigaction.sa_handler.type", string(context, "pointer"));
50+
configuration.config("platform.dirent.sizeof", 280);
51+
configuration.config("platform.dirent.d_name.offset", 19);
52+
configuration.config("platform.dirent.d_name.size", 256);
53+
configuration.config("platform.dirent.d_name.type", string(context, "char_array"));
54+
configuration.config("platform.dirent.d_type.offset", 18);
55+
configuration.config("platform.dirent.d_type.size", 1);
56+
configuration.config("platform.dirent.d_type.type", string(context, "uchar"));
5057
configuration.config("platform.addrinfo.sizeof", 48);
5158
configuration.config("platform.addrinfo.ai_flags.offset", 0);
5259
configuration.config("platform.addrinfo.ai_flags.size", 4);
@@ -378,6 +385,15 @@ public static void load(NativeConfiguration configuration, RubyContext context)
378385
configuration.config("platform.file.S_ISUID", 2048);
379386
configuration.config("platform.file.S_ISGID", 1024);
380387
configuration.config("platform.file.S_ISVTX", 512);
388+
configuration.config("platform.file.DT_BLK", 6);
389+
configuration.config("platform.file.DT_CHR", 2);
390+
configuration.config("platform.file.DT_DIR", 4);
391+
configuration.config("platform.file.DT_FIFO", 1);
392+
configuration.config("platform.file.DT_LNK", 10);
393+
configuration.config("platform.file.DT_REG", 8);
394+
configuration.config("platform.file.DT_SOCK", 12);
395+
configuration.config("platform.file.DT_UNKNOWN", 0);
396+
configuration.config("platform.file.AT_SYMLINK_NOFOLLOW", 256);
381397
configuration.config("platform.io.SEEK_SET", 0);
382398
configuration.config("platform.io.SEEK_CUR", 1);
383399
configuration.config("platform.io.SEEK_END", 2);

src/main/java/org/truffleruby/platform/LinuxARM64NativeConfiguration.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ public static void load(NativeConfiguration configuration, RubyContext context)
4747
configuration.config("platform.sigaction.sa_handler.offset", 0);
4848
configuration.config("platform.sigaction.sa_handler.size", 8);
4949
configuration.config("platform.sigaction.sa_handler.type", string(context, "pointer"));
50+
configuration.config("platform.dirent.sizeof", 280);
51+
configuration.config("platform.dirent.d_name.offset", 19);
52+
configuration.config("platform.dirent.d_name.size", 256);
53+
configuration.config("platform.dirent.d_name.type", string(context, "char_array"));
54+
configuration.config("platform.dirent.d_type.offset", 18);
55+
configuration.config("platform.dirent.d_type.size", 1);
56+
configuration.config("platform.dirent.d_type.type", string(context, "uchar"));
5057
configuration.config("platform.addrinfo.sizeof", 48);
5158
configuration.config("platform.addrinfo.ai_flags.offset", 0);
5259
configuration.config("platform.addrinfo.ai_flags.size", 4);
@@ -379,6 +386,15 @@ public static void load(NativeConfiguration configuration, RubyContext context)
379386
configuration.config("platform.file.S_ISUID", 2048);
380387
configuration.config("platform.file.S_ISGID", 1024);
381388
configuration.config("platform.file.S_ISVTX", 512);
389+
configuration.config("platform.file.DT_BLK", 6);
390+
configuration.config("platform.file.DT_CHR", 2);
391+
configuration.config("platform.file.DT_DIR", 4);
392+
configuration.config("platform.file.DT_FIFO", 1);
393+
configuration.config("platform.file.DT_LNK", 10);
394+
configuration.config("platform.file.DT_REG", 8);
395+
configuration.config("platform.file.DT_SOCK", 12);
396+
configuration.config("platform.file.DT_UNKNOWN", 0);
397+
configuration.config("platform.file.AT_SYMLINK_NOFOLLOW", 256);
382398
configuration.config("platform.io.SEEK_SET", 0);
383399
configuration.config("platform.io.SEEK_CUR", 1);
384400
configuration.config("platform.io.SEEK_END", 2);

src/main/ruby/truffleruby/core/dir.rb

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,7 @@ def rewind
9898

9999
def read
100100
ensure_open
101-
entry = Truffle::POSIX.truffleposix_readdir(@ptr)
102-
Errno.handle unless entry
103-
return if entry.empty?
104-
105-
entry = entry.force_encoding(@encoding)
106-
107-
if Encoding.default_external == Encoding::US_ASCII && !entry.valid_encoding?
108-
entry.force_encoding Encoding::ASCII_8BIT
109-
return entry
110-
end
111-
112-
enc = Encoding.default_internal
113-
enc ? entry.encode(enc) : entry
101+
Truffle::DirOperations.readdir_name(self)
114102
end
115103

116104
def close

0 commit comments

Comments
 (0)