Skip to content

Commit

Permalink
experiment: parallelize chmod and \r\n normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner committed Dec 15, 2024
1 parent c218bff commit 9cb0f37
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
72 changes: 69 additions & 3 deletions src/install/bin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -598,8 +598,62 @@ pub const Bin = extern struct {
}

if (comptime !Environment.isWindows) {
const pm = Install.PackageManager.get();
const task = CRLFNormalizerTask.init(abs_target, pm);
_ = pm.incrementPendingTasks(1);
_ = pm.pending_linking_tasks.fetchAdd(1, .monotonic);
pm.thread_pool.schedule(bun.ThreadPool.Batch.from(&task.task));
}
}

const ChmodTask = struct {
abs_target: [:0]const u8,
package_manager: *bun.install.PackageManager,
task: bun.ThreadPool.Task = .{ .callback = run },

pub usingnamespace bun.New(@This());

pub fn init(abs_target: [:0]const u8, package_manager: *bun.install.PackageManager) *ChmodTask {
return ChmodTask.new(.{
.abs_target = bun.default_allocator.dupeZ(u8, abs_target) catch bun.outOfMemory(),
.package_manager = package_manager,
});
}

pub fn run(task: *bun.ThreadPool.Task) void {
const this: *ChmodTask = @fieldParentPtr("task", task);
defer this.deinit();
_ = bun.sys.chmod(this.abs_target, umask | 0o777);
}

pub fn deinit(this: *ChmodTask) void {
_ = this.package_manager.decrementPendingTasks();
_ = this.package_manager.pending_linking_tasks.fetchSub(1, .monotonic);
this.package_manager.wake();
bun.default_allocator.free(this.abs_target);
this.destroy();
}
};

const CRLFNormalizerTask = struct {
abs_target: [:0]const u8,
package_manager: *bun.install.PackageManager,
task: bun.ThreadPool.Task = .{ .callback = run },

pub usingnamespace bun.New(@This());

pub fn init(abs_target: [:0]const u8, package_manager: *bun.install.PackageManager) *CRLFNormalizerTask {
return CRLFNormalizerTask.new(.{
.abs_target = bun.default_allocator.dupeZ(u8, abs_target) catch bun.outOfMemory(),
.package_manager = package_manager,
});
}

pub fn run(task: *bun.ThreadPool.Task) void {
const this: *CRLFNormalizerTask = @fieldParentPtr("task", task);
defer this.deinit();
// any error here is ignored
const bin = bun.sys.File.openat(bun.invalid_fd, abs_target, bun.O.RDWR, 0o664).unwrap() catch return;
const bin = bun.sys.File.openat(bun.invalid_fd, this.abs_target, bun.O.RDWR, 0o664).unwrap() catch return;
defer bin.close();

var shebang_buf: [1024]u8 = undefined;
Expand All @@ -617,7 +671,16 @@ pub const Bin = extern struct {
}
}
}
}

pub fn deinit(this: *CRLFNormalizerTask) void {
_ = this.package_manager.decrementPendingTasks();
_ = this.package_manager.pending_linking_tasks.fetchSub(1, .monotonic);
this.package_manager.wake();

bun.default_allocator.free(this.abs_target);
this.destroy();
}
};

fn createWindowsShim(this: *Linker, target: bun.FileDescriptor, abs_target: [:0]const u8, abs_dest: [:0]const u8, global: bool) void {
const WinBinLinkingShim = @import("./windows-shim/BinLinkingShim.zig");
Expand Down Expand Up @@ -708,7 +771,10 @@ pub const Bin = extern struct {
fn createSymlink(this: *Linker, abs_target: [:0]const u8, abs_dest: [:0]const u8, global: bool) void {
defer {
if (this.err == null) {
_ = bun.sys.chmod(abs_target, umask | 0o777);
const task = ChmodTask.init(abs_target, Install.PackageManager.get());
_ = task.package_manager.pending_linking_tasks.fetchAdd(1, .monotonic);
_ = task.package_manager.incrementPendingTasks(1);
task.package_manager.thread_pool.schedule(bun.ThreadPool.Batch.from(&task.task));
}
}

Expand Down
12 changes: 12 additions & 0 deletions src/install/install.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2692,6 +2692,7 @@ pub const PackageManager = struct {
/// every single time, because someone could edit the patchfile at anytime
pending_pre_calc_hashes: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
pending_tasks: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
pending_linking_tasks: std.atomic.Value(u32) = std.atomic.Value(u32).init(0),
total_tasks: u32 = 0,
preallocated_network_tasks: PreallocatedNetworkTasks = PreallocatedNetworkTasks.init(bun.default_allocator),
preallocated_resolve_tasks: PreallocatedTaskStore = PreallocatedTaskStore.init(bun.default_allocator),
Expand Down Expand Up @@ -14010,7 +14011,9 @@ pub const PackageManager = struct {

// need to make sure bins are linked before completing any remaining scripts.
// this can happen if a package fails to download

installer.linkRemainingBins(log_level);
this.sleepUntilLinkingFinishes();
installer.completeRemainingScripts(log_level);

while (this.pending_lifecycle_script_tasks.load(.monotonic) > 0) {
Expand All @@ -14033,6 +14036,15 @@ pub const PackageManager = struct {
return manager.pending_tasks.load(.monotonic);
}

pub fn sleepUntilLinkingFinishes(manager: *PackageManager) void {
const Closure = struct {
pub fn isDone(pm: *PackageManager) bool {
return pm.pending_linking_tasks.load(.monotonic) == 0;
}
};
manager.sleepUntil(manager, &Closure.isDone);
}

pub inline fn incrementPendingTasks(manager: *PackageManager, count: u32) u32 {
manager.total_tasks += count;
return manager.pending_tasks.fetchAdd(count, .monotonic);
Expand Down

0 comments on commit 9cb0f37

Please sign in to comment.