diff options
author | 2020-10-17 21:06:55 -0700 | |
---|---|---|
committer | 2020-11-23 21:57:44 -0800 | |
commit | 2677dbab1485d094a7dc291bfa47814c64068a85 (patch) | |
tree | 1805c6d951e55d5a07faa39fe088b68c23cebb23 /libs/cputimeinstate/testtimeinstate.cpp | |
parent | e42a54b17768ea80f198c1b00bc6c4797a4485d8 (diff) |
Use eBPF-based time-in-state monitoring for groups of threads
Bug: 169279846
Test: atest libtimeinstate_test
Change-Id: I69de04cd93f065e4e2e4d78b7bb5a35fea8811ca
Diffstat (limited to 'libs/cputimeinstate/testtimeinstate.cpp')
-rw-r--r-- | libs/cputimeinstate/testtimeinstate.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp index 0d5f412935..519689bb0c 100644 --- a/libs/cputimeinstate/testtimeinstate.cpp +++ b/libs/cputimeinstate/testtimeinstate.cpp @@ -19,6 +19,8 @@ #include <sys/sysinfo.h> +#include <pthread.h> +#include <semaphore.h> #include <numeric> #include <unordered_map> #include <vector> @@ -504,5 +506,85 @@ TEST(TimeInStateTest, GetCpuFreqs) { for (size_t i = 0; i < freqs->size(); ++i) EXPECT_EQ((*freqs)[i].size(), (*times)[i].size()); } +uint64_t timeNanos() { + struct timespec spec; + clock_gettime(CLOCK_MONOTONIC, &spec); + return spec.tv_sec * 1000000000 + spec.tv_nsec; +} + +// Keeps CPU busy with some number crunching +void useCpu() { + long sum = 0; + for (int i = 0; i < 100000; i++) { + sum *= i; + } +} + +sem_t pingsem, pongsem; + +void *testThread(void *) { + for (int i = 0; i < 10; i++) { + sem_wait(&pingsem); + useCpu(); + sem_post(&pongsem); + } + return nullptr; +} + +TEST(TimeInStateTest, GetAggregatedTaskCpuFreqTimes) { + uint64_t startTimeNs = timeNanos(); + + sem_init(&pingsem, 0, 1); + sem_init(&pongsem, 0, 0); + + pthread_t thread; + ASSERT_EQ(pthread_create(&thread, NULL, &testThread, NULL), 0); + + // This process may have been running for some time, so when we start tracking + // CPU time, the very first switch may include the accumulated time. + // Yield the remainder of this timeslice to the newly created thread. + sem_wait(&pongsem); + sem_post(&pingsem); + + pid_t tgid = getpid(); + startTrackingProcessCpuTimes(tgid); + + pid_t tid = pthread_gettid_np(thread); + startAggregatingTaskCpuTimes(tid, 42); + + // Play ping-pong with the other thread to ensure that both threads get + // some CPU time. + for (int i = 0; i < 9; i++) { + sem_wait(&pongsem); + useCpu(); + sem_post(&pingsem); + } + + pthread_join(thread, NULL); + + std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>> optionalMap = + getAggregatedTaskCpuFreqTimes(tgid, {0, 42}); + ASSERT_TRUE(optionalMap); + + std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>> map = *optionalMap; + ASSERT_EQ(map.size(), 2u); + + uint64_t testDurationNs = timeNanos() - startTimeNs; + for (auto pair : map) { + uint16_t aggregationKey = pair.first; + ASSERT_TRUE(aggregationKey == 0 || aggregationKey == 42); + + std::vector<std::vector<uint64_t>> timesInState = pair.second; + uint64_t totalCpuTime = 0; + for (size_t i = 0; i < timesInState.size(); i++) { + for (size_t j = 0; j < timesInState[i].size(); j++) { + totalCpuTime += timesInState[i][j]; + } + } + ASSERT_GT(totalCpuTime, 0ul); + ASSERT_LE(totalCpuTime, testDurationNs); + } +} + } // namespace bpf } // namespace android |