diff options
author | 2023-05-15 08:49:54 -0700 | |
---|---|---|
committer | 2023-05-15 08:49:54 -0700 | |
commit | dd11f02a45b9fc09eaf01afe9e94e073fd281e2a (patch) | |
tree | 76720ab476a083ef1e90b920621ada401ce28989 | |
parent | 1088a228028030bd88854b53dda248fa77f23727 (diff) | |
download | bun-dd11f02a45b9fc09eaf01afe9e94e073fd281e2a.tar.gz bun-dd11f02a45b9fc09eaf01afe9e94e073fd281e2a.tar.zst bun-dd11f02a45b9fc09eaf01afe9e94e073fd281e2a.zip |
[bun build] builds w/ sourcemaps get 15% faster
parallelize quoting source contents
-rw-r--r-- | src/bundler/bundle_v2.zig | 101 |
1 files changed, 71 insertions, 30 deletions
diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index d15f2d1e3..82e6bdc6d 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -3502,6 +3502,7 @@ const LinkerGraph = struct { entry_point_kind: EntryPoint.Kind = .none, line_offset_table: bun.sourcemap.LineOffsetTable.List = .{}, + quoted_source_contents: string = "", pub fn isEntryPoint(this: *const File) bool { return this.entry_point_kind.isEntryPoint(); @@ -3574,28 +3575,42 @@ const LinkerContext = struct { }; pub const SourceMapData = struct { - wait_group: sync.WaitGroup = undefined, - tasks: []Task = &.{}, + line_offset_wait_group: sync.WaitGroup = undefined, + line_offset_tasks: []Task = &.{}, + + quoted_contents_wait_group: sync.WaitGroup = undefined, + quoted_contents_tasks: []Task = &.{}, pub const Task = struct { ctx: *LinkerContext, source_index: Index.Int, - thread_task: ThreadPoolLib.Task = .{ .callback = &run }, + thread_task: ThreadPoolLib.Task = .{ .callback = &runLineOffset }, - pub fn run(thread_task: *ThreadPoolLib.Task) void { + pub fn runLineOffset(thread_task: *ThreadPoolLib.Task) void { var task = @fieldParentPtr(Task, "thread_task", thread_task); defer { task.ctx.markPendingTaskDone(); - task.ctx.source_maps.wait_group.finish(); + task.ctx.source_maps.line_offset_wait_group.finish(); } - SourceMapData.compute(task.ctx, ThreadPool.Worker.get(@fieldParentPtr(BundleV2, "linker", task.ctx)).allocator, task.source_index); + SourceMapData.computeLineOffsets(task.ctx, ThreadPool.Worker.get(@fieldParentPtr(BundleV2, "linker", task.ctx)).allocator, task.source_index); + } + + pub fn runQuotedSourceContents(thread_task: *ThreadPoolLib.Task) void { + var task = @fieldParentPtr(Task, "thread_task", thread_task); + defer { + task.ctx.markPendingTaskDone(); + task.ctx.source_maps.quoted_contents_wait_group.finish(); + } + + SourceMapData.computeQuotedSourceContents(task.ctx, ThreadPool.Worker.get(@fieldParentPtr(BundleV2, "linker", task.ctx)).allocator, task.source_index); } }; - pub fn compute(this: *LinkerContext, allocator: std.mem.Allocator, source_index: Index.Int) void { + pub fn computeLineOffsets(this: *LinkerContext, allocator: std.mem.Allocator, source_index: Index.Int) void { debug("Computing LineOffsetTable: {d}", .{source_index}); var line_offset_table: *bun.sourcemap.LineOffsetTable.List = &this.graph.files.items(.line_offset_table)[source_index]; + const source: *const Logger.Source = &this.parse_graph.input_files.items(.source)[source_index]; const approximate_line_count = this.graph.ast.items(.approximate_newline_count)[source_index]; @@ -3608,6 +3623,15 @@ const LinkerContext = struct { @intCast(i32, @truncate(u31, approximate_line_count)), ); } + + pub fn computeQuotedSourceContents(this: *LinkerContext, allocator: std.mem.Allocator, source_index: Index.Int) void { + debug("Computing Quoted Source Contents: {d}", .{source_index}); + var quoted_source_contents: *string = &this.graph.files.items(.quoted_source_contents)[source_index]; + + const source: *const Logger.Source = &this.parse_graph.input_files.items(.source)[source_index]; + var mutable = MutableString.initEmpty(allocator); + quoted_source_contents.* = (js_printer.quoteForJSON(source.contents, mutable, false) catch @panic("Out of memory")).list.items; + } }; fn isExternalDynamicImport(this: *LinkerContext, record: *const ImportRecord, source_index: u32) bool { @@ -3677,17 +3701,33 @@ const LinkerContext = struct { this: *LinkerContext, reachable: []const Index.Int, ) void { - this.source_maps.wait_group.init(); - this.source_maps.wait_group.counter = @truncate(u32, reachable.len); - this.source_maps.tasks = this.allocator.alloc(SourceMapData.Task, reachable.len) catch unreachable; + this.source_maps.line_offset_wait_group.init(); + this.source_maps.quoted_contents_wait_group.init(); + this.source_maps.line_offset_wait_group.counter = @truncate(u32, reachable.len); + this.source_maps.quoted_contents_wait_group.counter = @truncate(u32, reachable.len); + this.source_maps.line_offset_tasks = this.allocator.alloc(SourceMapData.Task, reachable.len) catch unreachable; + this.source_maps.quoted_contents_tasks = this.allocator.alloc(SourceMapData.Task, reachable.len) catch unreachable; + var batch = ThreadPoolLib.Batch{}; - for (reachable, this.source_maps.tasks) |source_index, *task| { - task.* = .{ + var second_batch = ThreadPoolLib.Batch{}; + for (reachable, this.source_maps.line_offset_tasks, this.source_maps.quoted_contents_tasks) |source_index, *line_offset, *quoted| { + line_offset.* = .{ + .ctx = this, + .source_index = source_index, + .thread_task = .{ .callback = &SourceMapData.Task.runLineOffset }, + }; + quoted.* = .{ .ctx = this, .source_index = source_index, + .thread_task = .{ .callback = &SourceMapData.Task.runQuotedSourceContents }, }; - batch.push(ThreadPoolLib.Batch.from(&task.thread_task)); + batch.push(ThreadPoolLib.Batch.from(&line_offset.thread_task)); + second_batch.push(ThreadPoolLib.Batch.from("ed.thread_task)); } + + // line offsets block sooner and are faster to compute, so we should schedule those first + batch.push(second_batch); + this.scheduleTasks(batch); } @@ -6683,6 +6723,7 @@ const LinkerContext = struct { var j = Joiner{}; const sources = c.parse_graph.input_files.items(.source); + const quoted_source_map_contents = c.graph.files.items(.quoted_source_contents); var source_index_to_sources_index = std.AutoHashMap(u32, u32).init(worker.allocator); defer source_index_to_sources_index.deinit(); @@ -6723,20 +6764,12 @@ const LinkerContext = struct { j.push("],\n \"sourcesContent\": [\n "); if (source_indices.len > 0) { - { - const contents = sources[source_indices[0]].contents; - var quote_buf = try MutableString.init(worker.allocator, contents.len); - quote_buf = try js_printer.quoteForJSON(contents, quote_buf, false); - j.push(quote_buf.list.items); - } + j.push(quoted_source_map_contents[source_indices[0]]); if (source_indices.len > 1) { for (source_indices[1..]) |index| { - const contents = sources[index].contents; - var quote_buf = try MutableString.init(worker.allocator, contents.len + 2 + ", ".len); - quote_buf.appendAssumeCapacity(",\n "); - quote_buf = try js_printer.quoteForJSON(contents, quote_buf, false); - j.push(quote_buf.list.items); + j.push(",\n "); + j.push(quoted_source_map_contents[index]); } } } @@ -8629,12 +8662,12 @@ const LinkerContext = struct { try c.parse_graph.pool.pool.doPtr(c.allocator, wait_group, ctx, generateJSRenamer, chunks); } - if (c.source_maps.tasks.len > 0) { - debug(" START {d} source maps", .{chunks.len}); - defer debug(" DONE {d} source maps", .{chunks.len}); - c.source_maps.wait_group.wait(); - c.allocator.free(c.source_maps.tasks); - c.source_maps.tasks.len = 0; + if (c.source_maps.line_offset_tasks.len > 0) { + debug(" START {d} source maps (line offset)", .{chunks.len}); + defer debug(" DONE {d} source maps (line offset)", .{chunks.len}); + c.source_maps.line_offset_wait_group.wait(); + c.allocator.free(c.source_maps.line_offset_tasks); + c.source_maps.line_offset_tasks.len = 0; } { var chunk_contexts = c.allocator.alloc(GenerateChunkCtx, chunks.len) catch unreachable; @@ -8679,6 +8712,14 @@ const LinkerContext = struct { wait_group.wait(); } + if (c.source_maps.quoted_contents_tasks.len > 0) { + debug(" START {d} source maps (quoted contents)", .{chunks.len}); + defer debug(" DONE {d} source maps (quoted contents)", .{chunks.len}); + c.source_maps.quoted_contents_wait_group.wait(); + c.allocator.free(c.source_maps.quoted_contents_tasks); + c.source_maps.quoted_contents_tasks.len = 0; + } + { debug(" START {d} postprocess chunks", .{chunks.len}); defer debug(" DONE {d} postprocess chunks", .{chunks.len}); |