Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for bthread cpu usage #2852

Merged
merged 1 commit into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/bthread/bthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,4 +554,12 @@ bthread_tag_t bthread_self_tag(void) {
: BTHREAD_TAG_DEFAULT;
}

uint64_t bthread_cpu_clock_ns(void) {
bthread::TaskGroup* g = bthread::tls_task_group;
if (g != NULL && !g->is_current_main_task()) {
return g->current_task_cpu_clock_ns();
}
return 0;
}

} // extern "C"
18 changes: 18 additions & 0 deletions src/bthread/bthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,24 @@ extern bthread_tag_t bthread_self_tag(void);
// Returns 0 on success, error code otherwise.
extern int bthread_once(bthread_once_t* once_control, void (*init_routine)());

/**
* @brief Retrieves the CPU time consumed by the current bthread.
*
* This function returns the CPU time (in nanoseconds) used by the current
* bthread, excluding time spent in blocking I/O operations. The result
* provides an accurate measure of CPU time utilized by the bthread's
* execution.
*
* @note The functionality of this function depends on the
* `bthread_enable_cpu_clock_stat` flag. Ensure this flag is enabled
* for the function to provide meaningful results. If the flag is
* disabled, the function may return an invalid value or behave
* unexpectedly.
*
* @return int64_t The CPU time in nanoseconds consumed by the bthread.
*/
extern uint64_t bthread_cpu_clock_ns(void);

__END_DECLS

#endif // BTHREAD_BTHREAD_H
19 changes: 18 additions & 1 deletion src/bthread/task_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ const bool ALLOW_UNUSED dummy_show_per_worker_usage_in_vars =
::GFLAGS_NS::RegisterFlagValidator(&FLAGS_show_per_worker_usage_in_vars,
pass_bool);

DEFINE_bool(bthread_enable_cpu_clock_stat, false,
"Enable CPU clock statistics for bthread");
const bool ALLOW_UNUSED dummy_bthread_enable_cpu_clock_stat = ::GFLAGS_NS::RegisterFlagValidator(&FLAGS_bthread_enable_cpu_clock_stat,
pass_bool);

BAIDU_VOLATILE_THREAD_LOCAL(TaskGroup*, tls_task_group, NULL);
// Sync with TaskMeta::local_storage when a bthread is created or destroyed.
// During running, the two fields may be inconsistent, use tls_bls as the
Expand All @@ -70,7 +75,7 @@ extern void return_keytable(bthread_keytable_pool_t*, KeyTable*);
// overhead of creation keytable, may be removed later.
BAIDU_VOLATILE_THREAD_LOCAL(void*, tls_unique_user_ptr, NULL);

const TaskStatistics EMPTY_STAT = { 0, 0 };
const TaskStatistics EMPTY_STAT = { 0, 0, 0 };

const size_t OFFSET_TABLE[] = {
#include "bthread/offset_inl.list"
Expand Down Expand Up @@ -255,6 +260,7 @@ int TaskGroup::init(size_t runqueue_capacity) {
_main_tid = m->tid;
_main_stack = stk;
_last_run_ns = butil::cpuwide_time_ns();
_last_cpu_clock_ns = 0;
return 0;
}

Expand Down Expand Up @@ -602,6 +608,17 @@ void TaskGroup::sched_to(TaskGroup** pg, TaskMeta* next_meta) {
const int64_t elp_ns = now - g->_last_run_ns;
g->_last_run_ns = now;
cur_meta->stat.cputime_ns += elp_ns;

if (FLAGS_bthread_enable_cpu_clock_stat) {
const int64_t cpu_thread_time = butil::cputhread_time_ns();
if (g->_last_cpu_clock_ns != 0) {
cur_meta->stat.cpu_usage_ns += cpu_thread_time - g->_last_cpu_clock_ns;
}
g->_last_cpu_clock_ns = cpu_thread_time;
} else {
g->_last_cpu_clock_ns = 0;
}

if (cur_meta->tid != g->main_tid()) {
g->_cumulated_cputime_ns += elp_ns;
}
Expand Down
11 changes: 11 additions & 0 deletions src/bthread/task_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,15 @@ class TaskGroup {

bthread_tag_t tag() const { return _tag; }

int64_t current_task_cpu_clock_ns() {
if (_last_cpu_clock_ns == 0) {
return 0;
}
int64_t total_ns = _cur_meta->stat.cpu_usage_ns;
total_ns += butil::cputhread_time_ns() - _last_cpu_clock_ns;
return total_ns;
}

private:
friend class TaskControl;

Expand Down Expand Up @@ -241,6 +250,8 @@ friend class TaskControl;
// last scheduling time
int64_t _last_run_ns;
int64_t _cumulated_cputime_ns;
// last thread cpu clock
int64_t _last_cpu_clock_ns;

size_t _nswitch;
RemainedFn _last_context_remained;
Expand Down
1 change: 1 addition & 0 deletions src/bthread/task_meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace bthread {
struct TaskStatistics {
int64_t cputime_ns;
int64_t nswitch;
int64_t cpu_usage_ns;
};

class KeyTable;
Expand Down
8 changes: 8 additions & 0 deletions src/butil/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,14 @@ inline int64_t cpuwide_time_ns() {
#endif // defined(BAIDU_INTERNAL)
}

// Get cpu clock time of the current thread in nanoseconds without the time spent in blocking I/O operations.
// Cost ~200ns
inline int64_t cputhread_time_ns() {
timespec now;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
return now.tv_sec * 1000000000L + now.tv_nsec;
}

inline int64_t cpuwide_time_us() {
return cpuwide_time_ns() / 1000L;
}
Expand Down
Loading