观察者效应优化

This commit is contained in:
2026-08-27 20:58:04 +08:00
parent 41b81c5c87
commit b9f19de776
8 changed files with 85 additions and 290 deletions
+2 -6
View File
@@ -23,14 +23,10 @@ struct Taskflow_Frame_Access {
Render_Frame& frame, std::size_t worker, std::uint64_t native_id,
std::size_t queue_size, std::size_t queue_capacity,
Clock::time_point entered, Clock::time_point started,
Clock::time_point finished, std::uint64_t cpu_entered_ns,
std::uint64_t cpu_started_ns, std::uint64_t cpu_duration_ns,
std::uint64_t cpu_cycles, std::uint64_t cooperative_wait_ns,
bool cpu_time_coarse);
Clock::time_point finished, std::uint64_t cooperative_wait_ns);
static void finish_task_observer(
Render_Frame& frame, std::size_t worker, std::size_t task,
Clock::time_point completed, std::uint64_t cpu_finished_ns,
std::uint64_t cpu_completed_ns) noexcept;
Clock::time_point completed) noexcept;
[[nodiscard]] static Taskflow_Graph_Token begin_graph(
Render_Frame& frame, Task_Graph& graph, std::string_view stage);
static void finish_graph(Taskflow_Graph_Token token,
+15 -19
View File
@@ -51,7 +51,7 @@ void Render_Frame::begin(Frame_Identity identity,
for (auto& measurement : d->measurements)
measurement.store(0, std::memory_order_relaxed);
d->taskflow_trace_requested.store(false, std::memory_order_relaxed);
d->taskflow_workers.clear();
for (auto& worker : d->taskflow_workers) worker.tasks.clear();
d->taskflow_graphs.clear();
d->markers[static_cast<std::size_t>(Frame_Trace_Marker::created)].store(encode_present_value(0), std::memory_order_relaxed);
}
@@ -177,7 +177,10 @@ Taskflow_Frame_Trace Render_Frame::take_taskflow_trace() {
static_cast<Frame_Trace_Measurement>(index),
decode_present_value(encoded)});
}
result.graphs = std::move(d->taskflow_graphs);
result.graphs.reserve(d->taskflow_graphs.size());
for (auto& graph : d->taskflow_graphs)
result.graphs.push_back(std::move(graph));
d->taskflow_graphs.clear();
for (auto& worker : d->taskflow_workers) {
for (auto& task : worker.tasks)
result.tasks.push_back(std::move(task));
@@ -341,9 +344,11 @@ Taskflow_Frame_Trace Render_Frame::take_taskflow_trace() {
void detail::Taskflow_Frame_Access::begin_capture(Render_Frame& frame, std::size_t workers) {
auto& data = *frame.d;
data.taskflow_workers.clear();
data.taskflow_workers.resize(workers);
for (auto& worker : data.taskflow_workers) worker.tasks.reserve(64);
for (auto& worker : data.taskflow_workers) {
worker.tasks.clear();
if (worker.tasks.capacity() < 64) worker.tasks.reserve(64);
}
data.taskflow_graphs.clear();
}
@@ -356,10 +361,7 @@ std::size_t detail::Taskflow_Frame_Access::append_task(
Render_Frame& frame, std::size_t worker, std::uint64_t native_id,
std::size_t queue_size, std::size_t queue_capacity,
Clock::time_point entered, Clock::time_point started,
Clock::time_point finished, std::uint64_t cpu_entered_ns,
std::uint64_t cpu_started_ns, std::uint64_t cpu_duration_ns,
std::uint64_t cpu_cycles, std::uint64_t cooperative_wait_ns,
bool cpu_time_coarse) {
Clock::time_point finished, std::uint64_t cooperative_wait_ns) {
auto& data = *frame.d;
if (worker >= data.taskflow_workers.size())
return std::numeric_limits<std::size_t>::max();
@@ -376,22 +378,15 @@ std::size_t detail::Taskflow_Frame_Access::append_task(
trace.finished_ms = elapsed_ms(finished);
trace.completed_ms = trace.finished_ms;
trace.duration_ms = std::max(0.0, trace.finished_ms - trace.started_ms);
trace.cpu_duration_ms = static_cast<double>(cpu_duration_ns) / 1'000'000.0;
trace.cpu_cycles = cpu_cycles;
trace.cooperative_wait_ms = static_cast<double>(cooperative_wait_ns) / 1'000'000.0;
trace.cpu_time_coarse = cpu_time_coarse;
trace.observer_entry_ms = std::max(0.0, trace.started_ms - trace.entered_ms);
trace.observer_entry_cpu_ms = cpu_started_ns >= cpu_entered_ns
? static_cast<double>(cpu_started_ns - cpu_entered_ns) / 1'000'000.0
: 0.0;
data.taskflow_workers[worker].tasks.push_back(std::move(trace));
return data.taskflow_workers[worker].tasks.size() - 1;
}
void detail::Taskflow_Frame_Access::finish_task_observer(
Render_Frame& frame, std::size_t worker, std::size_t task,
Clock::time_point completed, std::uint64_t cpu_finished_ns,
std::uint64_t cpu_completed_ns) noexcept {
Clock::time_point completed) noexcept {
auto& data = *frame.d;
if (worker >= data.taskflow_workers.size() ||
task >= data.taskflow_workers[worker].tasks.size()) return;
@@ -400,9 +395,6 @@ void detail::Taskflow_Frame_Access::finish_task_observer(
completed - data.created_at).count();
trace.observer_exit_ms = std::max(
0.0, trace.completed_ms - trace.finished_ms);
trace.observer_exit_cpu_ms = cpu_completed_ns >= cpu_finished_ns
? static_cast<double>(cpu_completed_ns - cpu_finished_ns) / 1'000'000.0
: 0.0;
}
detail::Taskflow_Graph_Token detail::Taskflow_Frame_Access::begin_graph(
@@ -411,6 +403,10 @@ detail::Taskflow_Graph_Token detail::Taskflow_Frame_Access::begin_graph(
graph.stage = stage;
graph.taskflow_name = taskflow.name();
graph.nodes = detail::Task_Graph_Access::nodes(taskflow);
for (auto& worker : frame.d->taskflow_workers) {
const auto required = worker.tasks.size() + graph.nodes.size();
if (worker.tasks.capacity() < required) worker.tasks.reserve(required);
}
graph.submitted_ms = std::chrono::duration<double, std::milli>(
Clock::now() - frame.d->created_at).count();
frame.d->taskflow_graphs.push_back(std::move(graph));
-5
View File
@@ -109,14 +109,9 @@ struct Taskflow_Task_Trace {
double finished_ms{}; /* Observer on_exit 进入,即任务体已经结束的时间。 */
double completed_ms{}; /* Observer on_exit 与按帧追踪写入全部结束的时间。 */
double duration_ms{}; /* 仅任务体 started 到 finished 的持续时间。 */
double cpu_duration_ms{}; /* 任务体独占当前 worker 片段的线程 CPU 时间;cooperative corun 期间不计入。 */
std::uint64_t cpu_cycles{}; /* Windows QueryThreadCycleTime 的独占 CPU 周期;用于短任务 CPU 活动判定,不直接换算秒。 */
double cooperative_wait_ms{}; /* Task_Graph::corun/corun_until 主动让出 Worker 的墙钟时间。 */
bool cpu_time_coarse{}; /* 当前平台的线程 CPU 时间源是否为低分辨率计费时钟(Windows GetThreadTimes)。 */
double observer_entry_ms{}; /* on_entry 诊断本身的耗时。 */
double observer_exit_ms{}; /* on_exit 诊断与按帧追踪写入的耗时。 */
double observer_entry_cpu_ms{}; /* on_entry 诊断实际消耗的 worker CPU 时间。 */
double observer_exit_cpu_ms{}; /* on_exit 诊断实际消耗的 worker CPU 时间。 */
double ready_ms{}; /* 前驱完成或根 run 提交后的估算就绪时间。 */
double queue_wait_ms{}; /* ready 到 entered 的估算 Executor 排队时间。 */
};
+36 -178
View File
@@ -72,32 +72,6 @@ std::uint64_t thread_cpu_cycles(HANDLE thread) noexcept {
: 0;
}
#endif
std::uint64_t current_thread_cpu_ns() noexcept {
#if defined(_WIN32)
return thread_cpu_ns(GetCurrentThread());
#elif defined(CLOCK_THREAD_CPUTIME_ID)
timespec value{};
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &value) != 0) return 0;
return static_cast<std::uint64_t>(value.tv_sec) * 1'000'000'000ULL +
static_cast<std::uint64_t>(value.tv_nsec);
#else
return 0;
#endif
}
std::uint64_t current_thread_cpu_cycles() noexcept {
#if defined(_WIN32)
return thread_cpu_cycles(GetCurrentThread());
#else
return 0;
#endif
}
constexpr bool thread_cpu_time_is_coarse() noexcept {
#if defined(_WIN32)
return true;
#else
return false;
#endif
}
struct Task_Observer : public tf::ObserverInterface {
private:
using Clock = std::chrono::steady_clock;
@@ -120,9 +94,9 @@ private:
std::atomic_uint64_t active_task_hash{};
std::atomic_uint64_t active_task_started_ns{};
std::atomic_uint64_t active_segment_started_ns{};
std::atomic_uint64_t active_segment_cpu_started_ns{};
#if defined(_WIN32)
std::atomic_uintptr_t native_thread_handle{}; /* Watchdog 只读的真实 Worker 线程句柄。 */
std::atomic_uint64_t cpu_time_origin_ns{}; /* 首次进入 Worker 时的累计线程 CPU,读取侧据此计算观测期增量。 */
std::atomic_uint64_t active_cpu_cycles{}; /* 连续片段最近一次采样的 Worker CPU 周期。 */
std::atomic_uint64_t active_cpu_progress_ns{}; /* CPU 周期最后前进的墙钟时刻。 */
#endif
@@ -130,32 +104,19 @@ private:
std::atomic_bool active_task_reported{};
std::atomic_uint64_t task_time_ns{};
std::atomic_uint64_t busy_time_ns{};
std::atomic_uint64_t cpu_time_ns{};
std::atomic_uint64_t min_task_time_ns{std::numeric_limits<std::uint64_t>::max()};
std::atomic_uint64_t max_task_time_ns{};
std::atomic_size_t max_predecessors{};
std::atomic_size_t max_successors{};
std::atomic_size_t max_strong_dependencies{};
std::atomic_size_t max_weak_dependencies{};
std::atomic_uint64_t first_task_time_ns{};
std::atomic_uint64_t last_task_time_ns{};
std::atomic_uint64_t longest_task_time_ns{};
std::atomic_size_t longest_task_hash{};
std::atomic<tf::TaskType> longest_task_type{tf::TaskType::UNDEFINED};
std::atomic<std::shared_ptr<const std::string>> longest_task_name{};
};
struct Start_Record {
Clock::time_point entered{}; /* Observer on_entry 进入时间。 */
Clock::time_point started{}; /* on_entry 完成、任务体即将执行的时间。 */
Clock::time_point segment_started{}; /* 当前连续独占 Worker 片段的起点。 */
std::uint64_t maximum_segment_ns{}; /* 已结束连续独占片段的最大墙钟。 */
std::uint64_t cpu_entered_ns{}; /* on_entry 进入时的 worker CPU 时间。 */
std::uint64_t cpu_started_ns{}; /* 任务体开始前的 worker CPU 时间,仅用于 Observer entry 统计。 */
std::uint64_t cpu_segment_started_ns{}; /* 当前任务独占 Worker 片段的线程 CPU 起点。 */
bool cpu_segment_active{}; /* CPU 累计值本身允许为 0,不能拿 0 当未启动哨兵。 */
std::uint64_t cpu_duration_ns{}; /* 已累计的任务独占 Worker CPU;嵌套 corun/子任务不计入。 */
std::uint64_t cpu_cycle_segment_started{}; /* Windows 当前独占片段的 QueryThreadCycleTime 起点。 */
std::uint64_t cpu_cycles{}; /* Windows 已累计的任务独占 CPU 周期。 */
Clock::time_point cooperative_wait_started{}; /* 主动 corun 让出 Worker 的墙钟起点。 */
std::uint64_t cooperative_wait_ns{}; /* 已累计 cooperative wait 墙钟。 */
Render_Frame* frame{}; /* 进入任务时唯一活动的按帧捕获。 */
@@ -167,7 +128,6 @@ private:
};
std::vector<std::vector<Start_Record>> starts;
std::vector<Clock::time_point> worker_busy_starts;
std::vector<std::uint64_t> worker_cpu_starts;
std::unique_ptr<Worker_Statistics[]> worker_statistics;
std::size_t worker_statistics_count{};
std::uint64_t worker_occupation_limit_ns{}; /* 单节点连续非 CPU 等待 Worker 的上限。 */
@@ -278,41 +238,6 @@ private:
}
}
}
static void close_cpu_segment(
Start_Record& active, std::uint64_t cpu_now_ns,
std::uint64_t cycle_now) noexcept {
if (!active.frame || !active.cpu_segment_active) return;
if (cpu_now_ns >= active.cpu_segment_started_ns)
active.cpu_duration_ns +=
cpu_now_ns - active.cpu_segment_started_ns;
#if defined(_WIN32)
if (cycle_now >= active.cpu_cycle_segment_started)
active.cpu_cycles += cycle_now - active.cpu_cycle_segment_started;
#else
static_cast<void>(cycle_now);
#endif
active.cpu_segment_started_ns = 0;
active.cpu_cycle_segment_started = 0;
active.cpu_segment_active = false;
}
static void close_cpu_segment(Start_Record& active) noexcept {
if (!active.frame || !active.cpu_segment_active) return;
close_cpu_segment(active, current_thread_cpu_ns(),
current_thread_cpu_cycles());
}
static void open_cpu_segment(
Start_Record& active, std::uint64_t cpu_now_ns,
std::uint64_t cycle_now) noexcept {
if (!active.frame) return;
active.cpu_segment_started_ns = cpu_now_ns;
active.cpu_cycle_segment_started = cycle_now;
active.cpu_segment_active = true;
}
static void open_cpu_segment(Start_Record& active) noexcept {
if (!active.frame) return;
open_cpu_segment(active, current_thread_cpu_ns(),
current_thread_cpu_cycles());
}
void pause_worker(std::size_t worker) noexcept {
if (worker >= starts.size() || starts[worker].empty()) return;
const auto now = Clock::now();
@@ -324,15 +249,12 @@ private:
active.maximum_segment_ns = std::max(
active.maximum_segment_ns, elapsed);
}
close_cpu_segment(active);
active.segment_started = {};
if (active.cooperative_wait_started == Clock::time_point{})
active.cooperative_wait_started = now;
active.cooperatively_suspended = true;
worker_statistics[worker].active_segment_started_ns.store(
0, std::memory_order_release);
worker_statistics[worker].active_segment_cpu_started_ns.store(
0, std::memory_order_release);
#if defined(_WIN32)
worker_statistics[worker].active_cpu_cycles.store(
0, std::memory_order_release);
@@ -352,17 +274,11 @@ private:
}
active.cooperatively_suspended = false;
active.segment_started = now;
open_cpu_segment(active);
worker_statistics[worker].active_segment_started_ns.store(
clock_ns(now), std::memory_order_release);
worker_statistics[worker].active_segment_cpu_started_ns.store(
current_thread_cpu_ns(), std::memory_order_release);
#if defined(_WIN32)
const auto handle = worker_statistics[worker].native_thread_handle.load(
std::memory_order_acquire);
worker_statistics[worker].active_cpu_cycles.store(
thread_cpu_cycles(reinterpret_cast<HANDLE>(handle)),
std::memory_order_release);
worker_statistics[worker].active_cpu_cycles.store(0,
std::memory_order_release);
worker_statistics[worker].active_cpu_progress_ns.store(
clock_ns(now), std::memory_order_release);
#endif
@@ -392,10 +308,9 @@ public:
void set_up(std::size_t workers) override {
starts.resize(workers);
worker_busy_starts.resize(workers);
worker_cpu_starts.resize(workers);
worker_statistics = std::make_unique<Worker_Statistics[]>(workers);
worker_statistics_count = workers;
for (auto& worker : starts) worker.reserve(8);
for (auto& worker : starts) worker.reserve(32);
watchdog_thread = std::thread([this] {
run_watchdog();
});
@@ -412,12 +327,11 @@ public:
GetCurrentProcess(), GetCurrentThread(),
GetCurrentProcess(), &duplicated, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
std::uintptr_t expected{};
if (!worker_state.native_thread_handle.compare_exchange_strong(
expected, reinterpret_cast<std::uintptr_t>(duplicated),
std::memory_order_release,
std::memory_order_relaxed))
CloseHandle(duplicated);
worker_state.cpu_time_origin_ns.store(
thread_cpu_ns(duplicated), std::memory_order_relaxed);
worker_state.native_thread_handle.store(
reinterpret_cast<std::uintptr_t>(duplicated),
std::memory_order_release);
}
}
#endif
@@ -429,19 +343,16 @@ public:
now - parent.segment_started).count());
parent.maximum_segment_ns = std::max(
parent.maximum_segment_ns, elapsed);
close_cpu_segment(parent);
parent.segment_started = {};
}
}
if (worker_starts.empty()) {
worker_busy_starts[worker.id()] = now;
worker_cpu_starts[worker.id()] = current_thread_cpu_ns();
}
if (worker_starts.empty()) worker_busy_starts[worker.id()] = now;
const auto queue_size = worker.queue_size();
const auto queue_capacity = worker.queue_capacity();
Start_Record record{};
record.entered = now;
record.cpu_entered_ns = current_thread_cpu_ns();
record.queue_size = worker.queue_size();
record.queue_capacity = worker.queue_capacity();
record.queue_size = queue_size;
record.queue_capacity = queue_capacity;
record.native_id = static_cast<std::uint64_t>(task.hash_value());
record.type = task.type();
worker_starts.push_back(std::move(record));
@@ -450,55 +361,30 @@ public:
const auto active_depth = worker_state.active_depth.fetch_add(
1, std::memory_order_relaxed) + 1;
update_max(worker_state.peak_active_depth, active_depth);
worker_state.current_queue_size.store(worker.queue_size(), std::memory_order_relaxed);
worker_state.current_queue_capacity.store(worker.queue_capacity(), std::memory_order_relaxed);
worker_state.current_queue_size.store(queue_size, std::memory_order_relaxed);
worker_state.current_queue_capacity.store(queue_capacity, std::memory_order_relaxed);
worker_state.active_task_hash.store(task.hash_value(), std::memory_order_relaxed);
worker_state.active_task_started_ns.store(clock_ns(now), std::memory_order_relaxed);
worker_state.active_segment_started_ns.store(clock_ns(now),
std::memory_order_release);
worker_state.active_segment_cpu_started_ns.store(
current_thread_cpu_ns(), std::memory_order_release);
#if defined(_WIN32)
const auto native_handle = worker_state.native_thread_handle.load(
std::memory_order_acquire);
worker_state.active_cpu_cycles.store(
thread_cpu_cycles(reinterpret_cast<HANDLE>(native_handle)),
std::memory_order_release);
worker_state.active_cpu_cycles.store(0, std::memory_order_release);
worker_state.active_cpu_progress_ns.store(
clock_ns(now), std::memory_order_release);
#endif
worker_state.active_task_type.store(task.type(), std::memory_order_relaxed);
worker_state.active_task_reported.store(false, std::memory_order_relaxed);
update_max(worker_state.peak_queue_size, worker.queue_size());
update_max(worker_state.max_queue_capacity, worker.queue_capacity());
update_max(worker_state.max_predecessors, task.num_predecessors());
update_max(worker_state.max_successors, task.num_successors());
update_max(worker_state.max_strong_dependencies,
task.num_strong_dependencies());
update_max(worker_state.max_weak_dependencies,
task.num_weak_dependencies());
update_max(worker_state.peak_queue_size, queue_size);
update_max(worker_state.max_queue_capacity, queue_capacity);
if (!task.name().empty()) worker_state.named_task_count.fetch_add(1, std::memory_order_relaxed);
update_first(worker_state.first_task_time_ns, clock_ns(now));
const auto task_cpu_started_ns = current_thread_cpu_ns();
const auto task_cpu_cycle_started = worker_starts.back().frame
? current_thread_cpu_cycles() : 0;
worker_starts.back().cpu_started_ns = task_cpu_started_ns;
worker_starts.back().cpu_segment_started_ns = task_cpu_started_ns;
worker_starts.back().cpu_cycle_segment_started =
task_cpu_cycle_started;
worker_starts.back().cpu_segment_active =
worker_starts.back().frame != nullptr;
worker_starts.back().started = Clock::now();
worker_starts.back().segment_started = worker_starts.back().started;
}
void on_exit(tf::WorkerView worker, tf::TaskView task) override {
const auto finished = Clock::now();
const auto cpu_finished_ns = current_thread_cpu_ns();
auto& worker_starts = starts[worker.id()];
auto& active = worker_starts.back();
const auto cpu_finished_cycles = active.frame
? current_thread_cpu_cycles() : 0;
close_cpu_segment(active, cpu_finished_ns, cpu_finished_cycles);
if (active.cooperative_wait_started != Clock::time_point{}) {
active.cooperative_wait_ns += static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(
@@ -538,9 +424,6 @@ public:
longest, elapsed, std::memory_order_relaxed)) {
worker_state.longest_task_hash.store(task.hash_value(), std::memory_order_relaxed);
worker_state.longest_task_type.store(task.type(), std::memory_order_relaxed);
worker_state.longest_task_name.store(
std::make_shared<const std::string>(task.name()),
std::memory_order_release);
}
worker_state.active_depth.fetch_sub(1, std::memory_order_relaxed);
std::optional<std::size_t> trace_task;
@@ -550,39 +433,27 @@ public:
*start.frame, worker.id(),
static_cast<std::uint64_t>(task.hash_value()),
start.queue_size, start.queue_capacity, start.entered,
start.started, finished, start.cpu_entered_ns,
start.cpu_started_ns, start.cpu_duration_ns,
start.cpu_cycles, start.cooperative_wait_ns,
thread_cpu_time_is_coarse());
start.started, finished, start.cooperative_wait_ns);
}
catch (...) {
/* Observer 不能让按需诊断分配失败改变渲染任务的完成语义。 */
}
}
const auto cpu_completed_ns = current_thread_cpu_ns();
const auto completed = Clock::now();
if (start.frame) {
if (trace_task)
detail::Taskflow_Frame_Access::finish_task_observer(
*start.frame, worker.id(), *trace_task, completed,
cpu_finished_ns, cpu_completed_ns);
*start.frame, worker.id(), *trace_task, completed);
}
if (worker_starts.empty()) {
auto busy = static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(
completed - worker_busy_starts[worker.id()]).count());
worker_state.busy_time_ns.fetch_add(busy, std::memory_order_relaxed);
const auto cpu_started = worker_cpu_starts[worker.id()];
const auto cpu = cpu_completed_ns >= cpu_started
? cpu_completed_ns - cpu_started
: 0;
worker_state.cpu_time_ns.fetch_add(cpu, std::memory_order_relaxed);
worker_state.active_task_hash.store(0, std::memory_order_relaxed);
worker_state.active_task_started_ns.store(0, std::memory_order_relaxed);
worker_state.active_segment_started_ns.store(0,
std::memory_order_release);
worker_state.active_segment_cpu_started_ns.store(
0, std::memory_order_release);
#if defined(_WIN32)
worker_state.active_cpu_cycles.store(0, std::memory_order_release);
worker_state.active_cpu_progress_ns.store(0,
@@ -601,8 +472,6 @@ public:
if (parent.cooperatively_suspended) {
worker_state.active_segment_started_ns.store(
0, std::memory_order_release);
worker_state.active_segment_cpu_started_ns.store(
0, std::memory_order_release);
#if defined(_WIN32)
worker_state.active_cpu_cycles.store(0,
std::memory_order_release);
@@ -611,20 +480,13 @@ public:
#endif
}
else {
const auto parent_cpu_started_ns = current_thread_cpu_ns();
const auto parent_cpu_cycle_started = parent.frame
? current_thread_cpu_cycles() : 0;
const auto parent_resumed = Clock::now();
parent.segment_started = parent_resumed;
open_cpu_segment(parent, parent_cpu_started_ns,
parent_cpu_cycle_started);
worker_state.active_segment_started_ns.store(
clock_ns(parent_resumed), std::memory_order_release);
worker_state.active_segment_cpu_started_ns.store(
parent_cpu_started_ns, std::memory_order_release);
#if defined(_WIN32)
worker_state.active_cpu_cycles.store(
parent_cpu_cycle_started, std::memory_order_release);
worker_state.active_cpu_cycles.store(0,
std::memory_order_release);
worker_state.active_cpu_progress_ns.store(
clock_ns(parent_resumed), std::memory_order_release);
#endif
@@ -657,10 +519,6 @@ public:
state.named_task_count = 0;
state.peak_observed_worker_queue_size = 0;
state.max_observed_worker_queue_capacity = 0;
state.max_predecessors = 0;
state.max_successors = 0;
state.max_strong_dependencies = 0;
state.max_weak_dependencies = 0;
state.total_task_time_ns = 0;
state.worker_busy_time_ns = 0;
state.worker_cpu_time_ns = 0;
@@ -696,7 +554,17 @@ public:
: std::string{};
target.task_time_ns = source.task_time_ns.load(std::memory_order_relaxed);
target.busy_time_ns = source.busy_time_ns.load(std::memory_order_relaxed);
target.cpu_time_ns = source.cpu_time_ns.load(std::memory_order_relaxed);
#if defined(_WIN32)
const auto native_handle = source.native_thread_handle.load(
std::memory_order_acquire);
const auto cpu_origin = source.cpu_time_origin_ns.load(
std::memory_order_acquire);
const auto cpu_now = thread_cpu_ns(
reinterpret_cast<HANDLE>(native_handle));
target.cpu_time_ns = cpu_now >= cpu_origin ? cpu_now - cpu_origin : 0;
#else
target.cpu_time_ns = 0;
#endif
target.non_cpu_time_ns = target.busy_time_ns > target.cpu_time_ns
? target.busy_time_ns - target.cpu_time_ns
: 0;
@@ -724,16 +592,6 @@ public:
state.max_observed_worker_queue_capacity = std::max(
state.max_observed_worker_queue_capacity,
target.max_observed_queue_capacity);
state.max_predecessors = std::max(state.max_predecessors,
source.max_predecessors.load(std::memory_order_relaxed));
state.max_successors = std::max(state.max_successors,
source.max_successors.load(std::memory_order_relaxed));
state.max_strong_dependencies = std::max(
state.max_strong_dependencies,
source.max_strong_dependencies.load(std::memory_order_relaxed));
state.max_weak_dependencies = std::max(
state.max_weak_dependencies,
source.max_weak_dependencies.load(std::memory_order_relaxed));
state.total_task_time_ns += target.task_time_ns;
state.worker_busy_time_ns += target.busy_time_ns;
state.worker_cpu_time_ns += target.cpu_time_ns;
@@ -765,8 +623,8 @@ public:
state.longest_task_time_ns = longest;
state.longest_task_hash = source.longest_task_hash.load(
std::memory_order_relaxed);
const auto name = source.longest_task_name.load(
std::memory_order_acquire);
const auto name = detail::taskflow_node_name(
state.longest_task_hash);
state.longest_task_name = name ? *name : std::string{};
state.longest_task_type = std::string(tf::to_string(
source.longest_task_type.load(std::memory_order_relaxed)));
-4
View File
@@ -80,10 +80,6 @@ struct Task_Runtime_State : State_Type<Task_Runtime_State_Tag> {
std::size_t named_task_count{};
std::size_t peak_observed_worker_queue_size{};
std::size_t max_observed_worker_queue_capacity{};
std::size_t max_predecessors{};
std::size_t max_successors{};
std::size_t max_strong_dependencies{};
std::size_t max_weak_dependencies{};
std::size_t longest_task_hash{};
std::string longest_task_name;
std::string longest_task_type;