summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-11-20 23:55:47 +0800
committerruki <[email protected]>2025-11-21 11:28:51 +0800
commit2d5076fbba423d24300996773d1fb7ecfcd1b02b (patch)
treee20f18af62ac437b8c5a7ad68d2d6e282211468d
parent0719de2b664bdfc82ce30534ed196bfc81fc072a (diff)
improve progress refresh timer
-rw-r--r--xmake/core/base/scheduler.lua5
-rw-r--r--xmake/modules/async/runjobs.lua56
-rw-r--r--xmake/modules/private/action/build/target.lua16
-rw-r--r--xmake/modules/private/check/checkers/clang/tidy.lua8
-rw-r--r--xmake/plugins/format/main.lua8
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})