Use copyfile backend in overlayfs by default

This commit is contained in:
Jarred Sumner
2025-07-23 12:09:15 -07:00
parent 16b124c6a8
commit 2d40e41fec
6 changed files with 63 additions and 109 deletions

View File

@@ -19,7 +19,7 @@ scripts_node: ?*Progress.Node = null,
progress_name_buf: [768]u8 = undefined,
progress_name_buf_dynamic: []u8 = &[_]u8{},
cpu_count: u32 = 0,
is_cache_directory_an_overlay_fs: ?bool = null,
is_cache_directory_remote: ?bun.sys.RemoteFileSystem = null,
track_installed_bin: TrackInstalledBin = .{
.none = {},
},
@@ -381,22 +381,22 @@ pub fn computeIsContinuousIntegration(this: *PackageManager) bool {
return this.env.isCI();
}
pub fn isCacheDirectoryRemote(this: *PackageManager) bool {
pub fn isCacheDirectoryRemote(this: *PackageManager) bun.sys.RemoteFileSystem {
if (comptime Environment.isWindows) {
// TODO:
return false;
return .none;
}
if (this.is_cache_directory_an_overlay_fs) |is_overlay_fs| {
return is_overlay_fs;
if (this.is_cache_directory_remote) |remote_fs| {
return remote_fs;
}
const statfs = bun.sys.statfs(this.cache_directory_path).unwrap() catch {
this.is_cache_directory_an_overlay_fs = false;
return false;
this.is_cache_directory_remote = .none;
return .none;
};
this.is_cache_directory_an_overlay_fs = bun.sys.isRemoteFilesystem(&statfs);
return this.is_cache_directory_an_overlay_fs.?;
this.is_cache_directory_remote = bun.sys.RemoteFileSystem.get(&statfs);
return this.is_cache_directory_remote.?;
}
pub inline fn isContinuousIntegration(this: *PackageManager) bool {
@@ -576,6 +576,34 @@ fn httpThreadOnInitError(err: HTTP.InitError, opts: HTTP.HTTPThread.InitOpts) no
Global.crash();
}
pub fn useCopyfileBackendIfFaster(this: *PackageManager) void {
if (this.options.do.auto_choose_backend) {
// Only do this once.
this.options.do.auto_choose_backend = false;
const PackageInstall = @import("./PackageInstall.zig").PackageInstall;
if (PackageInstall.supported_method == .hardlink) {
// Vercel builds:
//
// --backend=copyfile:
// 268 packages installed [5.06s]
//
// --backend=hardlink
// 268 packages installed [11.55s]
if (this.isCacheDirectoryRemote() == .overlayfs) {
if (PackageManager.verbose_install) {
if (this.options.node_linker == .hoisted) {
Output.prettyErrorln("<d>[PackageManager]<r> using <b>\"copyfile\"<r> backend instead of <b>\"hardlink\"<r> for faster installs in OverlayFS. Consider --linker=isolated to further speed up installs.", .{});
} else {
Output.prettyErrorln("<d>[PackageManager]<r> using <b>\"copyfile\"<r> backend instead of <b>\"hardlink\"<r> for faster installs in OverlayFS", .{});
}
}
PackageInstall.supported_method = .copyfile;
}
}
}
}
pub fn init(
ctx: Command.Context,
cli: CommandLineArguments,

View File

@@ -565,6 +565,7 @@ pub fn load(
if (cli.backend) |backend| {
PackageInstall.supported_method = backend;
this.do.auto_choose_backend = false;
}
this.do.update_to_latest = cli.latest;
@@ -666,7 +667,8 @@ pub const Do = packed struct(u16) {
trust_dependencies_from_args: bool = false,
update_to_latest: bool = false,
analyze: bool = false,
_: u4 = 0,
auto_choose_backend: bool = true,
_: u3 = 0,
};
pub const Enable = packed struct(u16) {

View File

@@ -270,7 +270,7 @@ pub fn runTasks(
if (manager.options.enable.manifest_cache) {
if (!bun.getRuntimeFeatureFlag(.BUN_FEATURE_FLAG_MANIFEST_CACHE_NO_SAVE_TTL)) {
if (!manager.isCacheDirectoryRemote()) {
if (manager.isCacheDirectoryRemote() == .none) {
Npm.PackageManifest.Serializer.saveAsync(
&entry.value_ptr.manifest,
manager.scopeForPackageName(name.slice()),

View File

@@ -83,6 +83,7 @@ pub fn installHoistedPackages(
var summary = PackageInstall.Summary{};
{
this.useCopyfileBackendIfFaster();
var iterator = Lockfile.Tree.Iterator(.node_modules).init(this.lockfile);
if (comptime Environment.isPosix) {
Bin.Linker.ensureUmask();

View File

@@ -620,6 +620,8 @@ pub fn installIsolatedPackages(
var seen_workspace_ids: std.AutoHashMapUnmanaged(PackageID, void) = .empty;
defer seen_workspace_ids.deinit(lockfile.allocator);
manager.useCopyfileBackendIfFaster();
var installer: Store.Installer = .{
.lockfile = lockfile,
.manager = manager,

View File

@@ -827,96 +827,10 @@ pub fn stat(path: [:0]const u8) Maybe(bun.Stat) {
}
}
pub fn isRemoteFilesystem(stat_fs: *const bun.StatFS) bool {
// The following filesystem types may appear in f_type:
// ADFS_SUPER_MAGIC 0xadf5
// AFFS_SUPER_MAGIC 0xadff
// AFS_SUPER_MAGIC 0x5346414f
// ANON_INODE_FS_MAGIC 0x09041934 /* Anonymous inode FS (for
// pseudofiles that have no name;
// e.g., epoll, signalfd, bpf) */
// AUTOFS_SUPER_MAGIC 0x0187
// BDEVFS_MAGIC 0x62646576
// BEFS_SUPER_MAGIC 0x42465331
// BFS_MAGIC 0x1badface
// BINFMTFS_MAGIC 0x42494e4d
// BPF_FS_MAGIC 0xcafe4a11
// BTRFS_SUPER_MAGIC 0x9123683e
// BTRFS_TEST_MAGIC 0x73727279
// CGROUP_SUPER_MAGIC 0x27e0eb /* Cgroup pseudo FS */
// CGROUP2_SUPER_MAGIC 0x63677270 /* Cgroup v2 pseudo FS */
// CIFS_MAGIC_NUMBER 0xff534d42
// CODA_SUPER_MAGIC 0x73757245
// COH_SUPER_MAGIC 0x012ff7b7
// CRAMFS_MAGIC 0x28cd3d45
// DEBUGFS_MAGIC 0x64626720
// DEVFS_SUPER_MAGIC 0x1373 /* Linux 2.6.17 and earlier */
// DEVPTS_SUPER_MAGIC 0x1cd1
// ECRYPTFS_SUPER_MAGIC 0xf15f
// EFIVARFS_MAGIC 0xde5e81e4
// EFS_SUPER_MAGIC 0x00414a53
// EXT_SUPER_MAGIC 0x137d /* Linux 2.0 and earlier */
// EXT2_OLD_SUPER_MAGIC 0xef51
// EXT2_SUPER_MAGIC 0xef53
// EXT3_SUPER_MAGIC 0xef53
// EXT4_SUPER_MAGIC 0xef53
// F2FS_SUPER_MAGIC 0xf2f52010
// FUSE_SUPER_MAGIC 0x65735546
// FUTEXFS_SUPER_MAGIC 0xbad1dea /* Unused */
// HFS_SUPER_MAGIC 0x4244
// HOSTFS_SUPER_MAGIC 0x00c0ffee
// HPFS_SUPER_MAGIC 0xf995e849
// HUGETLBFS_MAGIC 0x958458f6
// ISOFS_SUPER_MAGIC 0x9660
// JFFS2_SUPER_MAGIC 0x72b6
// JFS_SUPER_MAGIC 0x3153464a
// MINIX_SUPER_MAGIC 0x137f /* original minix FS */
// MINIX_SUPER_MAGIC2 0x138f /* 30 char minix FS */
// MINIX2_SUPER_MAGIC 0x2468 /* minix V2 FS */
// MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 FS, 30 char names */
// MINIX3_SUPER_MAGIC 0x4d5a /* minix V3 FS, 60 char names */
// MQUEUE_MAGIC 0x19800202 /* POSIX message queue FS */
// MSDOS_SUPER_MAGIC 0x4d44
// MTD_INODE_FS_MAGIC 0x11307854
// NCP_SUPER_MAGIC 0x564c
// NFS_SUPER_MAGIC 0x6969
// NILFS_SUPER_MAGIC 0x3434
// NSFS_MAGIC 0x6e736673
// NTFS_SB_MAGIC 0x5346544e
// OCFS2_SUPER_MAGIC 0x7461636f
// OPENPROM_SUPER_MAGIC 0x9fa1
// OVERLAYFS_SUPER_MAGIC 0x794c7630
// PIPEFS_MAGIC 0x50495045
// PROC_SUPER_MAGIC 0x9fa0 /* /proc FS */
// PSTOREFS_MAGIC 0x6165676c
// QNX4_SUPER_MAGIC 0x002f
// QNX6_SUPER_MAGIC 0x68191122
// RAMFS_MAGIC 0x858458f6
// REISERFS_SUPER_MAGIC 0x52654973
// ROMFS_MAGIC 0x7275
// SECURITYFS_MAGIC 0x73636673
// SELINUX_MAGIC 0xf97cff8c
// SMACK_MAGIC 0x43415d53
// SMB_SUPER_MAGIC 0x517b
// SMB2_MAGIC_NUMBER 0xfe534d42
// SOCKFS_MAGIC 0x534f434b
// SQUASHFS_MAGIC 0x73717368
// SYSFS_MAGIC 0x62656572
// SYSV2_SUPER_MAGIC 0x012ff7b6
// SYSV4_SUPER_MAGIC 0x012ff7b5
// TMPFS_MAGIC 0x01021994
// TRACEFS_MAGIC 0x74726163
// UDF_SUPER_MAGIC 0x15013346
// UFS_MAGIC 0x00011954
// USBDEVICE_SUPER_MAGIC 0x9fa2
// V9FS_MAGIC 0x01021997
// VXFS_SUPER_MAGIC 0xa501fcf5
// XENFS_SUPER_MAGIC 0xabba1974
// XENIX_SUPER_MAGIC 0x012ff7b4
// XFS_SUPER_MAGIC 0x58465342
// _XIAFS_SUPER_MAGIC 0x012fd16d
pub const RemoteFileSystem = enum {
overlayfs,
remote,
none,
const remote_fs_magic = [_]u32{
0xadf5, // ADFS_SUPER_MAGIC
@@ -930,7 +844,6 @@ pub fn isRemoteFilesystem(stat_fs: *const bun.StatFS) bool {
0x517b, // SMB_SUPER_MAGIC
0xfe534d42, // SMB2_MAGIC_NUMBER
0x65735546, // FUSE_SUPER_MAGIC
0x794c7630, // OVERLAYFS_SUPER_MAGIC
0x6165676c, // PSTOREFS_MAGIC
0x68191122, // QNX6_SUPER_MAGIC
0x62646576, // BDEVFS_MAGIC
@@ -940,14 +853,22 @@ pub fn isRemoteFilesystem(stat_fs: *const bun.StatFS) bool {
0x64626720, // DEBUGFS_MAGIC
};
for (remote_fs_magic) |magic| {
if (stat_fs.f_type & magic != 0) {
return true;
}
}
const OVERLAYFS_MAGIC = 0x794c7630;
return false;
}
pub fn get(stat_fs: *const bun.StatFS) RemoteFileSystem {
if (stat_fs.f_type == OVERLAYFS_MAGIC) {
return .overlayfs;
}
for (remote_fs_magic) |magic| {
if (stat_fs.f_type == magic) {
return .remote;
}
}
return .none;
}
};
pub fn statfs(path: [:0]const u8) Maybe(bun.StatFS) {
if (Environment.isWindows) {