Skip to content

Commit

Permalink
Minor formatting adjustments
Browse files Browse the repository at this point in the history
  • Loading branch information
jbachorik committed Jan 8, 2025
1 parent 0d6727e commit fe6aba3
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 132 deletions.
154 changes: 77 additions & 77 deletions ddprof-lib/src/main/cpp/wallClock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,13 @@ bool BaseWallClock::isEnabled() const {
}

void WallClockASGCT::initialize(Arguments& args) {
_collapsing = args._wall_collapsing;
OS::installSignalHandler(SIGVTALRM, sharedSignalHandler);
_collapsing = args._wall_collapsing;
OS::installSignalHandler(SIGVTALRM, sharedSignalHandler);
}

void WallClockJVMTI::timerLoop() {
// Check for enablement before attaching/dettaching the current thread
if (!isEnabled()) {
if (!isEnabled()) {
return;
}
// Attach to JVM as the first step
Expand All @@ -175,97 +175,97 @@ void WallClockJVMTI::timerLoop() {
int self = OS::threadId();

for (int i = 0; i < threads_count; i++) {
jthread thread = threads_ptr[i];
if (thread != nullptr) {
VMThread* nThread = VMThread::fromJavaThread(jni, thread);
if (nThread == nullptr) {
continue;
}
int tid = nThread->osThreadId();
if (tid != self && (!do_filter || Profiler::instance()->threadFilter()->accept(tid))) {
threads.push_back({nThread, thread});
}
jthread thread = threads_ptr[i];
if (thread != nullptr) {
VMThread* nThread = VMThread::fromJavaThread(jni, thread);
if (nThread == nullptr) {
continue;
}
int tid = nThread->osThreadId();
if (tid != self && (!do_filter || Profiler::instance()->threadFilter()->accept(tid))) {
threads.push_back({nThread, thread});
}
}
}
jvmti->Deallocate((unsigned char*)threads_ptr);
};

auto sampleThreads = [&](ThreadEntry& thread_entry, int& num_failures, int& threads_already_exited, int& permission_denied) {
jint max_stack_depth = (jint)Profiler::instance()->max_stack_depth();
jvmtiFrameInfo* frame_buffer = new jvmtiFrameInfo[max_stack_depth];
jvmtiEnv* jvmti = VM::jvmti();
static jint max_stack_depth = (jint)Profiler::instance()->max_stack_depth();
static jvmtiFrameInfo* frame_buffer = new jvmtiFrameInfo[max_stack_depth];
static jvmtiEnv* jvmti = VM::jvmti();

int num_frames = 0;
jvmtiError err = jvmti->GetStackTrace(thread_entry.java, 0, max_stack_depth, frame_buffer, &num_frames);
if (err != JVMTI_ERROR_NONE) {
num_failures++;
if (err == JVMTI_ERROR_THREAD_NOT_ALIVE) {
threads_already_exited++;
}
return false;
}
ExecutionEvent event;
VMThread* vm_thread = thread_entry.native;
int raw_thread_state = vm_thread->state();
bool is_initialized = raw_thread_state >= JVMJavaThreadState::_thread_in_native &&
raw_thread_state < JVMJavaThreadState::_thread_max_state;
ThreadState state = ThreadState::UNKNOWN;
ExecutionMode mode = ExecutionMode::UNKNOWN;
if (vm_thread && is_initialized) {
ThreadState os_state = vm_thread->osThreadState();
if (os_state != ThreadState::UNKNOWN) {
state = os_state;
}
mode = convertJvmExecutionState(raw_thread_state);
}
if (state == ThreadState::UNKNOWN) {
state = ThreadState::RUNNABLE;
}
event._thread_state = state;
event._execution_mode = mode;
event._weight = 1;
int num_frames = 0;
jvmtiError err = jvmti->GetStackTrace(thread_entry.java, 0, max_stack_depth, frame_buffer, &num_frames);
if (err != JVMTI_ERROR_NONE) {
num_failures++;
if (err == JVMTI_ERROR_THREAD_NOT_ALIVE) {
threads_already_exited++;
}
return false;
}
ExecutionEvent event;
VMThread* vm_thread = thread_entry.native;
int raw_thread_state = vm_thread->state();
bool is_initialized = raw_thread_state >= JVMJavaThreadState::_thread_in_native &&
raw_thread_state < JVMJavaThreadState::_thread_max_state;
ThreadState state = ThreadState::UNKNOWN;
ExecutionMode mode = ExecutionMode::UNKNOWN;
if (vm_thread && is_initialized) {
ThreadState os_state = vm_thread->osThreadState();
if (os_state != ThreadState::UNKNOWN) {
state = os_state;
}
mode = convertJvmExecutionState(raw_thread_state);
}
if (state == ThreadState::UNKNOWN) {
state = ThreadState::RUNNABLE;
}
event._thread_state = state;
event._execution_mode = mode;
event._weight = 1;

Profiler::instance()->recordExternalSample(1, thread_entry.native->osThreadId(), frame_buffer, num_frames, false, BCI_WALL, &event);
return true;
};
Profiler::instance()->recordExternalSample(1, thread_entry.native->osThreadId(), frame_buffer, num_frames, false, BCI_WALL, &event);
return true;
};

timerLoopCommon<ThreadEntry>(collectThreads, sampleThreads, _reservoir_size, _interval);
// Don't forget to detach the thread
VM::detachThread();
timerLoopCommon<ThreadEntry>(collectThreads, sampleThreads, _reservoir_size, _interval);
// Don't forget to detach the thread
VM::detachThread();
}

void WallClockASGCT::timerLoop() {
auto collectThreads = [&](std::vector<int>& tids) {
if (Profiler::instance()->threadFilter()->enabled()) {
Profiler::instance()->threadFilter()->collect(tids);
} else {
ThreadList *thread_list = OS::listThreads();
int tid = thread_list->next();
while (tid != -1) {
if (tid != OS::threadId()) {
tids.push_back(tid);
}
tid = thread_list->next();
}
delete thread_list;
if (Profiler::instance()->threadFilter()->enabled()) {
Profiler::instance()->threadFilter()->collect(tids);
} else {
ThreadList *thread_list = OS::listThreads();
int tid = thread_list->next();
while (tid != -1) {
if (tid != OS::threadId()) {
tids.push_back(tid);
}
tid = thread_list->next();
}
delete thread_list;
}
};

auto sampleThreads = [&](int tid, int& num_failures, int& threads_already_exited, int& permission_denied) {
if (!OS::sendSignalToThread(tid, SIGVTALRM)) {
num_failures++;
if (errno != 0) {
if (errno == ESRCH) {
threads_already_exited++;
} else if (errno == EPERM) {
permission_denied++;
} else {
Log::debug("unexpected error %s", strerror(errno));
}
}
return false;
}
return true;
if (!OS::sendSignalToThread(tid, SIGVTALRM)) {
num_failures++;
if (errno != 0) {
if (errno == ESRCH) {
threads_already_exited++;
} else if (errno == EPERM) {
permission_denied++;
} else {
Log::debug("unexpected error %s", strerror(errno));
}
}
return false;
}
return true;
};

timerLoopCommon<int>(collectThreads, sampleThreads, _reservoir_size, _interval);
Expand Down
108 changes: 54 additions & 54 deletions ddprof-lib/src/main/cpp/wallClock.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,63 +52,63 @@ class BaseWallClock : public Engine {

template <typename ThreadType, typename CollectThreadsFunc, typename SampleThreadsFunc>
void timerLoopCommon(CollectThreadsFunc collectThreads, SampleThreadsFunc sampleThreads, int reservoirSize, u64 interval) {
if (!_enabled.load(std::memory_order_acquire)) {
return;
if (!_enabled.load(std::memory_order_acquire)) {
return;
}

// Dither the sampling interval to introduce some randomness and prevent step-locking
const double stddev = ((double)_interval) / 10.0; // 10% standard deviation
// Set up random engine and normal distribution
std::random_device rd;
std::mt19937 generator(rd());
std::normal_distribution<double> distribution(interval, stddev);

std::vector<ThreadType> threads;
threads.reserve(reservoirSize);
int self = OS::threadId();
ThreadFilter* thread_filter = Profiler::instance()->threadFilter();
thread_filter->remove(self);

u64 startTime = TSC::ticks();
WallClockEpochEvent epoch(startTime);

ReservoirSampler<ThreadType> reservoir(reservoirSize);

while (_running.load(std::memory_order_relaxed)) {
collectThreads(threads);

int num_failures = 0;
int threads_already_exited = 0;
int permission_denied = 0;
std::vector<ThreadType> sample = reservoir.sample(threads);
for (ThreadType thread : sample) {
if (!sampleThreads(thread, num_failures, threads_already_exited, permission_denied)) {
continue;
}
}

// Dither the sampling interval to introduce some randomness and prevent step-locking
const double stddev = ((double)_interval) / 10.0; // 10% standard deviation
// Set up random engine and normal distribution
std::random_device rd;
std::mt19937 generator(rd());
std::normal_distribution<double> distribution(interval, stddev);

std::vector<ThreadType> threads;
threads.reserve(reservoirSize);
int self = OS::threadId();
ThreadFilter* thread_filter = Profiler::instance()->threadFilter();
thread_filter->remove(self);

u64 startTime = TSC::ticks();
WallClockEpochEvent epoch(startTime);

ReservoirSampler<ThreadType> reservoir(reservoirSize);

while (_running.load(std::memory_order_relaxed)) {
collectThreads(threads);

int num_failures = 0;
int threads_already_exited = 0;
int permission_denied = 0;
std::vector<ThreadType> sample = reservoir.sample(threads);
for (ThreadType thread : sample) {
if (!sampleThreads(thread, num_failures, threads_already_exited, permission_denied)) {
continue;
}
}

epoch.updateNumSamplableThreads(threads.size());
epoch.updateNumFailedSamples(num_failures);
epoch.updateNumSuccessfulSamples(sample.size() - num_failures);
epoch.updateNumExitedThreads(threads_already_exited);
epoch.updateNumPermissionDenied(permission_denied);
u64 endTime = TSC::ticks();
u64 duration = TSC::ticks_to_millis(endTime - startTime);
if (epoch.hasChanged() || duration >= 1000) {
epoch.endEpoch(duration);
Profiler::instance()->recordWallClockEpoch(self, &epoch);
epoch.newEpoch(endTime);
startTime = endTime;
} else {
epoch.clean();
}

threads.clear();
// Get a random sleep duration
// clamp the random interval to <1,2N-1>
// the probability of clamping is extremely small, close to zero
OS::sleep(std::min(std::max((long int)1, static_cast<long int>(distribution(generator))), ((_interval * 2) - 1)));
epoch.updateNumSamplableThreads(threads.size());
epoch.updateNumFailedSamples(num_failures);
epoch.updateNumSuccessfulSamples(sample.size() - num_failures);
epoch.updateNumExitedThreads(threads_already_exited);
epoch.updateNumPermissionDenied(permission_denied);
u64 endTime = TSC::ticks();
u64 duration = TSC::ticks_to_millis(endTime - startTime);
if (epoch.hasChanged() || duration >= 1000) {
epoch.endEpoch(duration);
Profiler::instance()->recordWallClockEpoch(self, &epoch);
epoch.newEpoch(endTime);
startTime = endTime;
} else {
epoch.clean();
}

threads.clear();
// Get a random sleep duration
// clamp the random interval to <1,2N-1>
// the probability of clamping is extremely small, close to zero
OS::sleep(std::min(std::max((long int)1, static_cast<long int>(distribution(generator))), ((_interval * 2) - 1)));
}
}

public:
Expand Down
1 change: 0 additions & 1 deletion ddprof-test/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ tasks.withType(Test).configureEach {

def keepRecordings = project.hasProperty("keepJFRs") || Boolean.parseBoolean(System.getenv("KEEP_JFRS"))

println("===> keepRecordings: ${keepRecordings}")
jvmArgs "-Dddprof_test.keep_jfrs=${keepRecordings}", '-Djdk.attach.allowAttachSelf', '-Djol.tryWithSudo=true',
"-Dddprof_test.config=${config}", '-XX:ErrorFile=build/hs_err_pid%p.log', '-XX:+ResizeTLAB',
'-Xmx512m'
Expand Down

0 comments on commit fe6aba3

Please sign in to comment.