Skip to content

Commit

Permalink
Merge pull request #2852 from icexin/bthread_cpu_time
Browse files Browse the repository at this point in the history
add support for bthread cpu usage
  • Loading branch information
cdjingit authored Dec 24, 2024
2 parents 282bc90 + 941f2e2 commit 103da1d
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 1 deletion.
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

0 comments on commit 103da1d

Please sign in to comment.