diff options
| author | ruki <[email protected]> | 2025-11-20 23:55:47 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-11-21 11:28:51 +0800 |
| commit | 2d5076fbba423d24300996773d1fb7ecfcd1b02b (patch) | |
| tree | e20f18af62ac437b8c5a7ad68d2d6e282211468d | |
| parent | 0719de2b664bdfc82ce30534ed196bfc81fc072a (diff) | |
improve progress refresh timer
| -rw-r--r-- | xmake/core/base/scheduler.lua | 5 | ||||
| -rw-r--r-- | xmake/modules/async/runjobs.lua | 56 | ||||
| -rw-r--r-- | xmake/modules/private/action/build/target.lua | 16 | ||||
| -rw-r--r-- | xmake/modules/private/check/checkers/clang/tidy.lua | 8 | ||||
| -rw-r--r-- | xmake/plugins/format/main.lua | 8 |
5 files changed, 61 insertions, 32 deletions
diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua index b11be7d4e..30385d504 100644 --- a/xmake/core/base/scheduler.lua +++ b/xmake/core/base/scheduler.lua @@ -1110,6 +1110,11 @@ function scheduler:enable(enabled) self._ENABLED = enabled end +-- cancel all timers +function scheduler:cancel_timers() + self:_timer():kill() +end + -- stop the scheduler loop function scheduler:stop() -- mark scheduler status as stopped and spank the poller:wait() diff --git a/xmake/modules/async/runjobs.lua b/xmake/modules/async/runjobs.lua index e08acc908..031e3a028 100644 --- a/xmake/modules/async/runjobs.lua +++ b/xmake/modules/async/runjobs.lua @@ -89,6 +89,22 @@ function _timer_loop(state) end end +-- the refresh loop for multirow progress (independent timer with its own timeout) +function _refresh_loop(state) + -- wait until all tasks have been started using semaphore + if state.refresh_semaphore then + state.refresh_semaphore:wait(-1) + end + -- start refreshing progress with independent timeout + while not state.stop do + os.sleep(state.refresh_timeout) + if not state.stop then + -- refresh multirow progress to update elapsed time + progress.refresh() + end + end +end + -- the progress loop function _progress_loop(state) local timeout = state.timeout @@ -207,6 +223,16 @@ function _consume_jobs_loop(state, run_in_remote) -- to avoid running the same task repeatedly, -- we need to update the completion count in advance. state.finished_count = state.finished_count + 1 + + -- check if all tasks have been started (all consumed, but may still be running) + if state.finished_count >= total and not state.all_tasks_started then + state.all_tasks_started = true + -- notify refresh loop that all tasks have been started + if state.refresh_semaphore then + state.refresh_semaphore:post(1) + end + end + job_func(job_index, total, {progress = state.progress_wrapper}) -- update progress @@ -295,9 +321,14 @@ function main(name, jobs, opt) state.total = opt.total or (type(jobs) == "table" and jobs:size()) or 1 state.comax = opt.comax and tonumber(opt.comax) or math.min(state.total, 4) state.timeout = opt.timeout or 500 + -- this timer only starts after all tasks have been consumed (waiting for completion), + -- so a shorter timeout (e.g., 100ms) is acceptable for quick refresh and doesn't affect performance + -- @see https://github.com/xmake-io/xmake/issues/7042 + state.refresh_timeout = opt.refresh_timeout or 100 state.group_name = name state.jobs_cb = type(jobs) == "function" and jobs or nil assert(state.timeout < 60000, "runjobs: invalid timeout!") + assert(state.refresh_timeout < 60000, "runjobs: invalid refresh_timeout!") -- build jobs queue if type(jobs) == "table" and jobs.build then @@ -320,6 +351,7 @@ function main(name, jobs, opt) -- run timer state.stop = false state.running_jobs_indices = {} + state.all_tasks_started = false local group_timer if opt.on_timer then state.on_timer = opt.on_timer @@ -333,6 +365,13 @@ function main(name, jobs, opt) scheduler.co_start_withopt({name = name .. "/tips", isolate = opt.isolate}, _progress_loop, state) end) end + + -- start independent refresh timer for multirow progress + local group_refresh_timer = nil + local need_refresh_timer = progress.is_multirow() + if need_refresh_timer then + group_refresh_timer = state.group_name .. "/refresh" + end -- run jobs local distcc = opt.distcc @@ -347,6 +386,10 @@ function main(name, jobs, opt) if distcc then state.distcc_semaphore = scheduler.co_semaphore(state.group_name .. "/distcc", 0) end + -- create semaphore for refresh loop to wait for all tasks started + if need_refresh_timer then + state.refresh_semaphore = scheduler.co_semaphore(state.group_name .. "/refresh", 0) + end -- @note we can set `remote_only = true` to run all jobs in remote only local local_comax = 0 if not opt.remote_only then @@ -363,6 +406,13 @@ function main(name, jobs, opt) end end end) + + -- start refresh timer after semaphore is created + if need_refresh_timer then + scheduler.co_group_begin(group_refresh_timer, function (co_group) + scheduler.co_start_withopt({name = name .. "/refresh", isolate = opt.isolate}, _refresh_loop, state) + end) + end -- wait all jobs exited scheduler.co_group_wait(state.group_name) @@ -372,6 +422,12 @@ function main(name, jobs, opt) state.stop = true scheduler.co_group_wait(group_timer) end + + -- wait refresh timer job exited + if group_refresh_timer then + state.stop = true + scheduler.co_group_wait(group_refresh_timer) + end -- restore isolated environments if co_running and opt.isolate then diff --git a/xmake/modules/private/action/build/target.lua b/xmake/modules/private/action/build/target.lua index c3d21f399..d623744b4 100644 --- a/xmake/modules/private/action/build/target.lua +++ b/xmake/modules/private/action/build/target.lua @@ -799,14 +799,6 @@ function run_targetjobs(targets_root, opt) remote_only = opt.remote_only, progress_factor = opt.progress_factor } - -- Only set timer for multirow progress mode - if progress_utils.is_multirow() then - runjobs_opt.timeout = 1000 - runjobs_opt.on_timer = function (running_indices) - -- Periodically refresh multirow progress to update elapsed time - progress_utils.refresh() - end - end async_runjobs(job_kind, jobgraph, runjobs_opt) os.cd(curdir) return true @@ -827,14 +819,6 @@ function run_filejobs(targets_root, opt) remote_only = opt.remote_only, progress_factor = opt.progress_factor } - -- Only set timer for multirow progress mode - if progress_utils.is_multirow() then - runjobs_opt.timeout = 1000 - runjobs_opt.on_timer = function (running_indices) - -- Periodically refresh multirow progress to update elapsed time - progress_utils.refresh() - end - end async_runjobs(job_kind, jobgraph, runjobs_opt) os.cd(curdir) return true diff --git a/xmake/modules/private/check/checkers/clang/tidy.lua b/xmake/modules/private/check/checkers/clang/tidy.lua index 03568eb6e..963bd1bdc 100644 --- a/xmake/modules/private/check/checkers/clang/tidy.lua +++ b/xmake/modules/private/check/checkers/clang/tidy.lua @@ -160,14 +160,6 @@ function _check_sourcefiles(clang_tidy, sourcefiles, opt) comax = opt.jobs or os.default_njob(), showtips = false } - -- Only set timer for multirow progress mode - if progress.is_multirow() then - runjobs_opt.timeout = 1000 - runjobs_opt.on_timer = function (running_indices) - -- Periodically refresh multirow progress to update elapsed time - progress.refresh() - end - end runjobs("checker.tidy", function (index, total, job_opt) local sourcefile = sourcefiles[index] local tidy_argv = table.join(argv, {sourcefile}) diff --git a/xmake/plugins/format/main.lua b/xmake/plugins/format/main.lua index 7a4c53394..768901f6b 100644 --- a/xmake/plugins/format/main.lua +++ b/xmake/plugins/format/main.lua @@ -221,14 +221,6 @@ function main() comax = jobs, showtips = false } - -- Only set timer for multirow progress mode - if progress.is_multirow() then - runjobs_opt.timeout = 1000 - runjobs_opt.on_timer = function (running_indices) - -- Periodically refresh multirow progress to update elapsed time - progress.refresh() - end - end runjobs("clang-format", function (index, total, opt) local sourcefile = sourcefiles[index] local format_argv = table.join(argv, {sourcefile}) |
