authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-12 13:53:41+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-12 17:51:31+01:00
log71baa5e769b3b82468736a60e0725a94da9be4e9
tree34831cde53f7e9908877f3dbcf926185eb0f1a70
parent5bb5aaf932b8ed30aebfbb0036e1532abfc6af46
signaturelock-open Commit is signed but in an unrecognized format.

compiler: improve progress output

Update the estimated total items for the codegen and link progress nodes earlier. Rather than waiting for the main thread to dispatch the tasks, we can add the item to the estimated total as soon as we queue the main task. The only difference is we need to complete it even in error cases.

4 files changed, 31 insertions(+), 3 deletions(-)

src/Compilation.zig+15-3
...@@ -848,6 +848,8 @@ const Job = union(enum) {...@@ -848,6 +848,8 @@ const Job = union(enum) {
848 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that848 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
849 /// all types are resolved before the linker task is queued.849 /// all types are resolved before the linker task is queued.
850 /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately.850 /// If the backend does not support `Zcu.Feature.separate_thread`, codegen and linking happen immediately.
851 /// Before queueing this `Job`, increase the estimated total item count for both
852 /// `comp.zcu.?.codegen_prog_node` and `comp.link_prog_node`.
851 codegen_func: struct {853 codegen_func: struct {
852 func: InternPool.Index,854 func: InternPool.Index,
853 /// The AIR emitted from analyzing `func`; owned by this `Job` in `gpa`.855 /// The AIR emitted from analyzing `func`; owned by this `Job` in `gpa`.
...@@ -857,12 +859,15 @@ const Job = union(enum) {...@@ -857,12 +859,15 @@ const Job = union(enum) {
857 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that859 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
858 /// all types are resolved before the linker task is queued.860 /// all types are resolved before the linker task is queued.
859 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.861 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
862 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
860 link_nav: InternPool.Nav.Index,863 link_nav: InternPool.Nav.Index,
861 /// Queue a `link.ZcuTask` to emit debug information for this container type.864 /// Queue a `link.ZcuTask` to emit debug information for this container type.
862 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that865 /// This `Job` exists (instead of the `link.ZcuTask` being directly queued) to ensure that
863 /// all types are resolved before the linker task is queued.866 /// all types are resolved before the linker task is queued.
864 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.867 /// If the backend does not support `Zcu.Feature.separate_thread`, the task is run immediately.
868 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
865 link_type: InternPool.Index,869 link_type: InternPool.Index,
870 /// Before queueing this `Job`, increase the estimated total item count for `comp.link_prog_node`.
866 update_line_number: InternPool.TrackedInst.Index,871 update_line_number: InternPool.TrackedInst.Index,
867 /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.872 /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
868 /// This may be its first time being analyzed, or it may be outdated.873 /// This may be its first time being analyzed, or it may be outdated.
...@@ -4592,11 +4597,17 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -4592,11 +4597,17 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
4592 const zcu = comp.zcu.?;4597 const zcu = comp.zcu.?;
4593 const gpa = zcu.gpa;4598 const gpa = zcu.gpa;
4594 var air = func.air;4599 var air = func.air;
4595 errdefer air.deinit(gpa);4600 errdefer {
4601 zcu.codegen_prog_node.completeOne();
4602 comp.link_prog_node.completeOne();
4603 air.deinit(gpa);
4604 }
4596 if (!air.typesFullyResolved(zcu)) {4605 if (!air.typesFullyResolved(zcu)) {
4597 // Type resolution failed in a way which affects this function. This is a transitive4606 // Type resolution failed in a way which affects this function. This is a transitive
4598 // failure, but it doesn't need recording, because this function semantically depends4607 // failure, but it doesn't need recording, because this function semantically depends
4599 // on the failed type, so when it is changed the function is updated.4608 // on the failed type, so when it is changed the function is updated.
4609 zcu.codegen_prog_node.completeOne();
4610 comp.link_prog_node.completeOne();
4600 air.deinit(gpa);4611 air.deinit(gpa);
4601 return;4612 return;
4602 }4613 }
...@@ -4606,7 +4617,6 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -4606,7 +4617,6 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
4606 .value = undefined,4617 .value = undefined,
4607 };4618 };
4608 assert(zcu.pending_codegen_jobs.rmw(.Add, 1, .monotonic) > 0); // the "Code Generation" node hasn't been ended4619 assert(zcu.pending_codegen_jobs.rmw(.Add, 1, .monotonic) > 0); // the "Code Generation" node hasn't been ended
4609 zcu.codegen_prog_node.increaseEstimatedTotalItems(1);
4610 // This value is used as a heuristic to avoid queueing too much AIR/MIR at once (hence4620 // This value is used as a heuristic to avoid queueing too much AIR/MIR at once (hence
4611 // using a lot of memory). If this would cause too many AIR bytes to be in-flight, we4621 // using a lot of memory). If this would cause too many AIR bytes to be in-flight, we
4612 // will block on the `dispatchZcuLinkTask` call below.4622 // will block on the `dispatchZcuLinkTask` call below.
...@@ -4640,6 +4650,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -4640,6 +4650,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
4640 if (nav.analysis != null) {4650 if (nav.analysis != null) {
4641 const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index });4651 const unit: InternPool.AnalUnit = .wrap(.{ .nav_val = nav_index });
4642 if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {4652 if (zcu.failed_analysis.contains(unit) or zcu.transitive_failed_analysis.contains(unit)) {
4653 comp.link_prog_node.completeOne();
4643 return;4654 return;
4644 }4655 }
4645 }4656 }
...@@ -4648,6 +4659,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -4648,6 +4659,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
4648 // Type resolution failed in a way which affects this `Nav`. This is a transitive4659 // Type resolution failed in a way which affects this `Nav`. This is a transitive
4649 // failure, but it doesn't need recording, because this `Nav` semantically depends4660 // failure, but it doesn't need recording, because this `Nav` semantically depends
4650 // on the failed type, so when it is changed the `Nav` will be updated.4661 // on the failed type, so when it is changed the `Nav` will be updated.
4662 comp.link_prog_node.completeOne();
4651 return;4663 return;
4652 }4664 }
4653 comp.dispatchZcuLinkTask(tid, .{ .link_nav = nav_index });4665 comp.dispatchZcuLinkTask(tid, .{ .link_nav = nav_index });
...@@ -4659,6 +4671,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {...@@ -4659,6 +4671,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
4659 // Type resolution failed in a way which affects this type. This is a transitive4671 // Type resolution failed in a way which affects this type. This is a transitive
4660 // failure, but it doesn't need recording, because this type semantically depends4672 // failure, but it doesn't need recording, because this type semantically depends
4661 // on the failed type, so when that is changed, this type will be updated.4673 // on the failed type, so when that is changed, this type will be updated.
4674 comp.link_prog_node.completeOne();
4662 return;4675 return;
4663 }4676 }
4664 comp.dispatchZcuLinkTask(tid, .{ .link_type = ty });4677 comp.dispatchZcuLinkTask(tid, .{ .link_type = ty });
...@@ -7460,7 +7473,6 @@ pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) vo...@@ -7460,7 +7473,6 @@ pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) vo
7460/// The reason for the double-queue here is that the first queue ensures any7473/// The reason for the double-queue here is that the first queue ensures any
7461/// resolve_type_fully tasks are complete before this dispatch function is called.7474/// resolve_type_fully tasks are complete before this dispatch function is called.
7462fn dispatchZcuLinkTask(comp: *Compilation, tid: usize, task: link.ZcuTask) void {7475fn dispatchZcuLinkTask(comp: *Compilation, tid: usize, task: link.ZcuTask) void {
7463 comp.link_prog_node.increaseEstimatedTotalItems(1);
7464 if (!comp.separateCodegenThreadOk()) {7476 if (!comp.separateCodegenThreadOk()) {
7465 assert(tid == 0);7477 assert(tid == 0);
7466 if (task == .link_func) {7478 if (task == .link_func) {
src/Sema.zig+8
...@@ -2992,6 +2992,7 @@ fn zirStructDecl(...@@ -2992,6 +2992,7 @@ fn zirStructDecl(
2992 if (zcu.comp.config.use_llvm) break :codegen_type;2992 if (zcu.comp.config.use_llvm) break :codegen_type;
2993 if (block.ownerModule().strip) break :codegen_type;2993 if (block.ownerModule().strip) break :codegen_type;
2994 // This job depends on any resolve_type_fully jobs queued up before it.2994 // This job depends on any resolve_type_fully jobs queued up before it.
2995 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
2995 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });2996 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2996 }2997 }
2997 try sema.declareDependency(.{ .interned = wip_ty.index });2998 try sema.declareDependency(.{ .interned = wip_ty.index });
...@@ -3266,6 +3267,7 @@ fn zirEnumDecl(...@@ -3266,6 +3267,7 @@ fn zirEnumDecl(
3266 if (zcu.comp.config.use_llvm) break :codegen_type;3267 if (zcu.comp.config.use_llvm) break :codegen_type;
3267 if (block.ownerModule().strip) break :codegen_type;3268 if (block.ownerModule().strip) break :codegen_type;
3268 // This job depends on any resolve_type_fully jobs queued up before it.3269 // This job depends on any resolve_type_fully jobs queued up before it.
3270 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3269 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });3271 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
3270 }3272 }
3271 return Air.internedToRef(wip_ty.index);3273 return Air.internedToRef(wip_ty.index);
...@@ -3385,6 +3387,7 @@ fn zirUnionDecl(...@@ -3385,6 +3387,7 @@ fn zirUnionDecl(
3385 if (zcu.comp.config.use_llvm) break :codegen_type;3387 if (zcu.comp.config.use_llvm) break :codegen_type;
3386 if (block.ownerModule().strip) break :codegen_type;3388 if (block.ownerModule().strip) break :codegen_type;
3387 // This job depends on any resolve_type_fully jobs queued up before it.3389 // This job depends on any resolve_type_fully jobs queued up before it.
3390 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3388 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });3391 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
3389 }3392 }
3390 try sema.declareDependency(.{ .interned = wip_ty.index });3393 try sema.declareDependency(.{ .interned = wip_ty.index });
...@@ -3473,6 +3476,7 @@ fn zirOpaqueDecl(...@@ -3473,6 +3476,7 @@ fn zirOpaqueDecl(
3473 if (zcu.comp.config.use_llvm) break :codegen_type;3476 if (zcu.comp.config.use_llvm) break :codegen_type;
3474 if (block.ownerModule().strip) break :codegen_type;3477 if (block.ownerModule().strip) break :codegen_type;
3475 // This job depends on any resolve_type_fully jobs queued up before it.3478 // This job depends on any resolve_type_fully jobs queued up before it.
3479 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3476 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });3480 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
3477 }3481 }
3478 try sema.addTypeReferenceEntry(src, wip_ty.index);3482 try sema.addTypeReferenceEntry(src, wip_ty.index);
...@@ -20105,6 +20109,7 @@ fn structInitAnon(...@@ -20105,6 +20109,7 @@ fn structInitAnon(
20105 codegen_type: {20109 codegen_type: {
20106 if (zcu.comp.config.use_llvm) break :codegen_type;20110 if (zcu.comp.config.use_llvm) break :codegen_type;
20107 if (block.ownerModule().strip) break :codegen_type;20111 if (block.ownerModule().strip) break :codegen_type;
20112 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
20108 try zcu.comp.queueJob(.{ .link_type = wip.index });20113 try zcu.comp.queueJob(.{ .link_type = wip.index });
20109 }20114 }
20110 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);20115 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
...@@ -21417,6 +21422,7 @@ fn reifyEnum(...@@ -21417,6 +21422,7 @@ fn reifyEnum(
21417 if (zcu.comp.config.use_llvm) break :codegen_type;21422 if (zcu.comp.config.use_llvm) break :codegen_type;
21418 if (block.ownerModule().strip) break :codegen_type;21423 if (block.ownerModule().strip) break :codegen_type;
21419 // This job depends on any resolve_type_fully jobs queued up before it.21424 // This job depends on any resolve_type_fully jobs queued up before it.
21425 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
21420 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });21426 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
21421 }21427 }
21422 return Air.internedToRef(wip_ty.index);21428 return Air.internedToRef(wip_ty.index);
...@@ -21671,6 +21677,7 @@ fn reifyUnion(...@@ -21671,6 +21677,7 @@ fn reifyUnion(
21671 if (zcu.comp.config.use_llvm) break :codegen_type;21677 if (zcu.comp.config.use_llvm) break :codegen_type;
21672 if (block.ownerModule().strip) break :codegen_type;21678 if (block.ownerModule().strip) break :codegen_type;
21673 // This job depends on any resolve_type_fully jobs queued up before it.21679 // This job depends on any resolve_type_fully jobs queued up before it.
21680 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
21674 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });21681 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
21675 }21682 }
21676 try sema.declareDependency(.{ .interned = wip_ty.index });21683 try sema.declareDependency(.{ .interned = wip_ty.index });
...@@ -22026,6 +22033,7 @@ fn reifyStruct(...@@ -22026,6 +22033,7 @@ fn reifyStruct(
22026 if (zcu.comp.config.use_llvm) break :codegen_type;22033 if (zcu.comp.config.use_llvm) break :codegen_type;
22027 if (block.ownerModule().strip) break :codegen_type;22034 if (block.ownerModule().strip) break :codegen_type;
22028 // This job depends on any resolve_type_fully jobs queued up before it.22035 // This job depends on any resolve_type_fully jobs queued up before it.
22036 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
22029 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });22037 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
22030 }22038 }
22031 try sema.declareDependency(.{ .interned = wip_ty.index });22039 try sema.declareDependency(.{ .interned = wip_ty.index });
src/Sema/LowerZon.zig+1
...@@ -195,6 +195,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter...@@ -195,6 +195,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
195 codegen_type: {195 codegen_type: {
196 if (pt.zcu.comp.config.use_llvm) break :codegen_type;196 if (pt.zcu.comp.config.use_llvm) break :codegen_type;
197 if (self.block.ownerModule().strip) break :codegen_type;197 if (self.block.ownerModule().strip) break :codegen_type;
198 pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
198 try pt.zcu.comp.queueJob(.{ .link_type = wip.index });199 try pt.zcu.comp.queueJob(.{ .link_type = wip.index });
199 }200 }
200 break :ty wip.finish(ip, new_namespace_index);201 break :ty wip.finish(ip, new_namespace_index);
src/Zcu/PerThread.zig+7
...@@ -1321,6 +1321,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr...@@ -1321,6 +1321,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
1321 }1321 }
13221322
1323 // This job depends on any resolve_type_fully jobs queued up before it.1323 // This job depends on any resolve_type_fully jobs queued up before it.
1324 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
1324 try zcu.comp.queueJob(.{ .link_nav = nav_id });1325 try zcu.comp.queueJob(.{ .link_nav = nav_id });
1325 }1326 }
13261327
...@@ -1717,6 +1718,8 @@ fn analyzeFuncBody(...@@ -1717,6 +1718,8 @@ fn analyzeFuncBody(
1717 }1718 }
17181719
1719 // This job depends on any resolve_type_fully jobs queued up before it.1720 // This job depends on any resolve_type_fully jobs queued up before it.
1721 zcu.codegen_prog_node.increaseEstimatedTotalItems(1);
1722 comp.link_prog_node.increaseEstimatedTotalItems(1);
1720 try comp.queueJob(.{ .codegen_func = .{1723 try comp.queueJob(.{ .codegen_func = .{
1721 .func = func_index,1724 .func = func_index,
1722 .air = air,1725 .air = air,
...@@ -1799,6 +1802,7 @@ fn createFileRootStruct(...@@ -1799,6 +1802,7 @@ fn createFileRootStruct(
1799 codegen_type: {1802 codegen_type: {
1800 if (file.mod.?.strip) break :codegen_type;1803 if (file.mod.?.strip) break :codegen_type;
1801 // This job depends on any resolve_type_fully jobs queued up before it.1804 // This job depends on any resolve_type_fully jobs queued up before it.
1805 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
1802 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });1806 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
1803 }1807 }
1804 zcu.setFileRootType(file_index, wip_ty.index);1808 zcu.setFileRootType(file_index, wip_ty.index);
...@@ -3827,6 +3831,7 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!...@@ -3827,6 +3831,7 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!
3827 const result = try pt.zcu.intern_pool.getExtern(pt.zcu.gpa, pt.tid, key);3831 const result = try pt.zcu.intern_pool.getExtern(pt.zcu.gpa, pt.tid, key);
3828 if (result.new_nav.unwrap()) |nav| {3832 if (result.new_nav.unwrap()) |nav| {
3829 // This job depends on any resolve_type_fully jobs queued up before it.3833 // This job depends on any resolve_type_fully jobs queued up before it.
3834 pt.zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3830 try pt.zcu.comp.queueJob(.{ .link_nav = nav });3835 try pt.zcu.comp.queueJob(.{ .link_nav = nav });
3831 if (pt.zcu.comp.debugIncremental()) try pt.zcu.incremental_debug_state.newNav(pt.zcu, nav);3836 if (pt.zcu.comp.debugIncremental()) try pt.zcu.incremental_debug_state.newNav(pt.zcu, nav);
3832 }3837 }
...@@ -3974,6 +3979,7 @@ fn recreateStructType(...@@ -3974,6 +3979,7 @@ fn recreateStructType(
3974 codegen_type: {3979 codegen_type: {
3975 if (file.mod.?.strip) break :codegen_type;3980 if (file.mod.?.strip) break :codegen_type;
3976 // This job depends on any resolve_type_fully jobs queued up before it.3981 // This job depends on any resolve_type_fully jobs queued up before it.
3982 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3977 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });3983 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
3978 }3984 }
39793985
...@@ -4066,6 +4072,7 @@ fn recreateUnionType(...@@ -4066,6 +4072,7 @@ fn recreateUnionType(
4066 codegen_type: {4072 codegen_type: {
4067 if (file.mod.?.strip) break :codegen_type;4073 if (file.mod.?.strip) break :codegen_type;
4068 // This job depends on any resolve_type_fully jobs queued up before it.4074 // This job depends on any resolve_type_fully jobs queued up before it.
4075 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
4069 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });4076 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
4070 }4077 }
40714078