Skip to content

Commit

Permalink
Add API for CPU cycle counter
Browse files Browse the repository at this point in the history
Summary: Add an API for getting CPU cycle counter, when available. Falls back to the OS API when not.

Reviewed By: jpporto

Differential Revision: D36144469

fbshipit-source-id: b7c4168533b6b306be75fcb50603fe2152c88b4a
  • Loading branch information
kodafb authored and facebook-github-bot committed May 17, 2022
1 parent f909be4 commit 50f73f9
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 0 deletions.
4 changes: 4 additions & 0 deletions include/hermes/Support/OSCompat.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ std::vector<bool> sched_getaffinity();
/// or -1 on error.
int sched_getcpu();

/// \return a monotonically increasing count of time, where the unit depends on
/// the implementation.
uint64_t cpu_cycle_counter();

#ifdef _WINDOWS

#define STDIN_FILENO 0
Expand Down
15 changes: 15 additions & 0 deletions lib/Support/OSCompatPosix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,21 @@ int sched_getcpu() {
}
#endif

uint64_t cpu_cycle_counter() {
#if defined(__aarch64__)
// Clang's builtin causes SIGILL on some 64-bit ARM environments.
uint64_t cnt;
__asm __volatile("mrs %0, cntvct_el0" : "=&r"(cnt));
return cnt;
#elif __has_builtin(__builtin_readcyclecounter)
return __builtin_readcyclecounter();
#else
timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return t.tv_sec * 1000LL * 1000LL * 1000LL + t.tv_nsec;
#endif
}

bool set_env(const char *name, const char *value) {
// Enforce the contract of this function that value must not be empty
assert(*value != '\0' && "value cannot be empty string");
Expand Down
13 changes: 13 additions & 0 deletions lib/Support/OSCompatWindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define NOMINMAX // do not define min/max macros
#include <windows.h>

#include <intrin.h>
#include <io.h>
#include <psapi.h>

Expand Down Expand Up @@ -407,6 +408,18 @@ int sched_getcpu() {
return -1;
}

uint64_t cpu_cycle_counter() {
#if defined(_MSC_VER)
return __rdtsc();
#elif __has_builtin(__builtin_readcyclecounter)
return __builtin_readcyclecounter();
#else
LARGE_INTEGER cnt;
QueryPerformanceCounter(&cnt);
return cnt;
#endif
}

bool set_env(const char *name, const char *value) {
// Setting an env var to empty requires a lot of hacks on Windows
assert(*value != '\0' && "value cannot be empty string");
Expand Down
6 changes: 6 additions & 0 deletions unittests/Support/OSCompatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ TEST(OSCompatTest, CurrentRSS) {
EXPECT_GE(oscompat::current_rss(), beginRSS);
}

TEST(OSCompatTest, CpuCycles) {
uint64_t start = oscompat::cpu_cycle_counter();
uint64_t end = oscompat::cpu_cycle_counter();
EXPECT_LE(start, end);
}

#ifdef __linux__
TEST(OSCompatTest, Scheduling) {
// At least one CPU should be set.
Expand Down

0 comments on commit 50f73f9

Please sign in to comment.