mruby-dir: implement Dir.entries in c for improved performance

Moved Dir.entries from Ruby to C implementation to eliminate
Ruby loop overhead and array allocation inefficiencies.
Builds result array directly in C for better performance.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-08-17 07:07:53 +09:00
parent 7f03e0f6a6
commit c699b211d7
2 changed files with 33 additions and 18 deletions
-18
View File
@@ -43,24 +43,6 @@ class Dir
alias pos= seek
class << self
#
# call-seq:
# Dir.entries(dirname) -> array
#
# Returns an array containing all of the filenames in the given directory.
# Will raise a SystemCallError if the named directory doesn't exist.
#
# Dir.entries("testdir") #=> [".", "..", "config.h", "main.rb"]
#
def entries(path)
a = []
self.open(path) do |d|
while s = d.read
a << s
end
end
a
end
#
# call-seq:
+33
View File
@@ -5,6 +5,7 @@
*/
#include <mruby.h>
#include <mruby/array.h>
#include <mruby/class.h>
#include <mruby/data.h>
#include <mruby/error.h>
@@ -421,6 +422,37 @@ mrb_dir_tell(mrb_state *mrb, mrb_value self)
#endif
}
/*
* call-seq:
* Dir.entries(dirname) -> array
*
* Returns an array containing all of the filenames in the given directory.
* Will raise a SystemCallError if the named directory doesn't exist.
*/
static mrb_value
mrb_dir_entries(mrb_state *mrb, mrb_value klass)
{
const char *path;
DIR *dir;
struct dirent *dp;
mrb_value ary;
mrb_get_args(mrb, "z", &path);
dir = opendir(path);
if (dir == NULL) {
mrb_sys_fail(mrb, path);
}
ary = mrb_ary_new(mrb);
while ((dp = readdir(dir)) != NULL) {
mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, dp->d_name));
}
closedir(dir);
return ary;
}
void
mrb_mruby_dir_gem_init(mrb_state *mrb)
{
@@ -435,6 +467,7 @@ mrb_mruby_dir_gem_init(mrb_state *mrb)
mrb_define_class_method_id(mrb, d, MRB_SYM(_chdir), mrb_dir_chdir, MRB_ARGS_REQ(1));
mrb_define_class_method_id(mrb, d, MRB_SYM(chroot), mrb_dir_chroot, MRB_ARGS_REQ(1));
mrb_define_class_method_id(mrb, d, MRB_SYM_Q(empty), mrb_dir_empty, MRB_ARGS_REQ(1));
mrb_define_class_method_id(mrb, d, MRB_SYM(entries), mrb_dir_entries, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, d, MRB_SYM(close), mrb_dir_close, MRB_ARGS_NONE());
mrb_define_method_id(mrb, d, MRB_SYM(initialize), mrb_dir_init, MRB_ARGS_REQ(1));