Project

General

Profile

Actions

Feature #21987

open

Assume `chdir(2)` isn't called and cache `rb_dir_getwd_ospath()`

Feature #21987: Assume `chdir(2)` isn't called and cache `rb_dir_getwd_ospath()`

Added by byroot (Jean Boussier) 3 days ago. Updated 2 days ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:125217]

Description

Context

I'm looking at optimizing Ruby applications boot time, and one very common operation that seems wasteful is that when interpreting relative paths
we keep calling ruby_getcwd(), even though its result almost never changes (Dir.chdir calls are rare).

We have 3 distinct implementations of ruby_getcwd() depending on the platform, but generally speaking it involves:

  • One or multiple syscalls (on macOS: open + fnctl + stat + close).
  • malloc + free
  • strdup + free
  • For some implementations, allocating a T_DATA to avoid leaks in case of failure.

Measure

Out of curiosity I measured our monolith. Just booting we end up calling getcwd(2) 6931 times, for a total of 90ms spent in rb_dir_getwd_ospath(), but the caching would allow to save a bit more than that, as callers would no longer need to manage that memory.

Proposal

I propose that we cache the result of ruby_getcwd(), and only flush the cache when Dir.chdir is called.

Compatibility concern

This however assumes that C extensions or other native libraries never call chdir(2) after executing Ruby, or at least always reset it before yielding back to Ruby.

I'm not aware of any C extension currently doing this, but it would be interesting to perform a gem-codesearch.

If necessary we can provide void ruby_cwd_changed(void) to reset the cache after calling chdir(2).

Actions

Also available in: PDF Atom