Skip to content
Draft
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
11 changes: 11 additions & 0 deletions ddprof-lib/src/main/cpp/arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,17 @@ Error Arguments::parse(const char *args) {
}
}

CASE("wallscope")
if (value == NULL || value[0] == 0) {
msg = "wallscope must be 'context' or 'all'";
} else if (strcmp(value, "context") == 0) {
_wall_scope = WALL_SCOPE_CONTEXT;
} else if (strcmp(value, "all") == 0) {
_wall_scope = WALL_SCOPE_ALL;
} else {
msg = "wallscope must be 'context' or 'all'";
}

CASE("nativemem")
_nativemem = value == NULL ? 0 : parseUnits(value, BYTES);
if (_nativemem < 0) {
Expand Down
12 changes: 12 additions & 0 deletions ddprof-lib/src/main/cpp/arguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ enum WallclockSampler {
JVMTI
};

enum WallScope {
WALL_SCOPE_LEGACY,
WALL_SCOPE_CONTEXT,
WALL_SCOPE_ALL
};

enum Clock {
CLK_DEFAULT,
CLK_TSC,
Expand Down Expand Up @@ -161,6 +167,10 @@ class Arguments {
}

public:
bool wallScopeAllThreads() const {
return _wall_scope == WALL_SCOPE_ALL;
}

Action _action;
Ring _ring;
const char *_event;
Expand All @@ -171,6 +181,7 @@ class Arguments {
bool _wall_precheck;
int _wall_threads_per_tick;
WallclockSampler _wallclock_sampler;
WallScope _wall_scope;
long _memory;
bool _record_allocations;
bool _record_liveness;
Expand Down Expand Up @@ -212,6 +223,7 @@ class Arguments {
_wall_precheck(false),
_wall_threads_per_tick(DEFAULT_WALL_THREADS_PER_TICK),
_wallclock_sampler(ASGCT),
_wall_scope(WALL_SCOPE_CONTEXT),
_memory(-1),
_record_allocations(false),
_record_liveness(false),
Expand Down
9 changes: 8 additions & 1 deletion ddprof-lib/src/main/cpp/counters.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
X(THREAD_NAMES_COUNT, "thread_names_count") \
X(THREAD_FILTER_PAGES, "thread_filter_pages") \
X(THREAD_FILTER_BYTES, "thread_filter_bytes") \
X(THREAD_FILTER_CAPACITY_EXHAUSTED, "thread_filter_capacity_exhausted") \
X(JMETHODID_SKIPPED, "jmethodid_skipped_count") \
X(CODECACHE_NATIVE_SIZE_BYTES, "codecache_native_size_bytes") \
X(CODECACHE_NATIVE_COUNT, "native_codecache_count") \
Expand All @@ -66,10 +67,16 @@
X(AGCT_NATIVE_NO_JAVA_CONTEXT, "agct_native_no_java_context") \
X(AGCT_BLOCKED_IN_VM, "agct_blocked_in_vm") \
X(SKIPPED_WALLCLOCK_UNWINDS, "skipped_wallclock_unwinds") \
X(WC_SIGNAL_SUPPRESSED_SAMPLED_RUN, "wc_signals_suppressed_sampled_run") \
X(WC_SIGNAL_SUPPRESSED_OWNED_BLOCK, "wc_signals_suppressed_owned_block") \
X(WC_UNOWNED_BLOCKED_SUPPRESSED, "wc_unowned_blocked_suppressed") \
X(WC_UNOWNED_BLOCKED_RECORDED, "wc_unowned_blocked_recorded") \
X(WC_SIGNAL_QUEUE_FULL, "wc_signals_queue_full") \
X(TASK_BLOCK_EMITTED, "task_block_emitted") \
X(TASK_BLOCK_SKIPPED_TRACE_CONTEXT, "task_block_skipped_trace_context") \
X(TASK_BLOCK_SKIPPED_TOO_SHORT, "task_block_skipped_too_short") \
X(TASK_BLOCK_STACK_CAPTURE_FAILED, "task_block_stack_capture_failed") \
X(TASK_BLOCK_RECORD_FAILED, "task_block_record_failed") \
X(TASK_BLOCK_DROPPED_ROTATION, "task_block_dropped_rotation") \
X(UNWINDING_TIME_ASYNC, "unwinding_ticks_async") \
X(UNWINDING_TIME_JVMTI, "unwinding_ticks_jvmti") \
X(CALLTRACE_STORAGE_DROPPED, "calltrace_storage_dropped_traces") \
Expand Down
22 changes: 16 additions & 6 deletions ddprof-lib/src/main/cpp/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class ExecutionEvent : public Event {
OSThreadState _thread_state;
ExecutionMode _execution_mode;
u64 _weight;
u32 _call_trace_id;
u64 _call_trace_id;

ExecutionEvent()
: Event(), _thread_state(OSThreadState::RUNNABLE), _execution_mode(ExecutionMode::UNKNOWN),
Expand Down Expand Up @@ -122,13 +122,13 @@ class WallClockEpochEvent {
u32 _num_failed_samples;
u32 _num_exited_threads;
u32 _num_permission_denied;
u64 _num_suppressed_sampled_run;
u64 _num_suppressed_owned_block;

WallClockEpochEvent(u64 start_time)
: _dirty(false), _start_time(start_time), _duration_millis(0),
_num_samplable_threads(0), _num_successful_samples(0),
_num_failed_samples(0), _num_exited_threads(0),
_num_permission_denied(0), _num_suppressed_sampled_run(0) {}
_num_permission_denied(0), _num_suppressed_owned_block(0) {}

bool hasChanged() { return _dirty; }

Expand Down Expand Up @@ -167,10 +167,10 @@ class WallClockEpochEvent {
}
}

void addNumSuppressedSampledRun(u64 n) {
void addNumSuppressedOwnedBlock(u64 n) {
if (n > 0) {
_dirty = true;
_num_suppressed_sampled_run += n;
_num_suppressed_owned_block += n;
}
}

Expand All @@ -181,7 +181,7 @@ class WallClockEpochEvent {
void newEpoch(u64 start_time) {
_dirty = false;
_start_time = start_time;
_num_suppressed_sampled_run = 0;
_num_suppressed_owned_block = 0;
}
};

Expand All @@ -206,4 +206,14 @@ typedef struct QueueTimeEvent {
u32 _queueLength;
} QueueTimeEvent;

typedef struct TaskBlockEvent {
u64 _start;
u64 _end;
u64 _blocker;
u64 _unblockingSpanId;
Context _ctx;
u64 _callTraceId;
OSThreadState _observedBlockingState;
} TaskBlockEvent;

#endif // _EVENT_H
32 changes: 31 additions & 1 deletion ddprof-lib/src/main/cpp/flightRecorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1873,6 +1873,21 @@ void Recording::recordMethodSample(Buffer *buf, int tid, u64 call_trace_id,
flushIfNeeded(buf);
}

void Recording::recordTaskBlock(Buffer *buf, int tid, TaskBlockEvent *event) {
int start = buf->skip(1);
buf->putVar64(T_TASK_BLOCK);
buf->putVar64(event->_start);
buf->putVar64(event->_end - event->_start);
buf->putVar64(tid);
buf->putVar64(event->_blocker);
buf->putVar64(event->_unblockingSpanId);
buf->putVar64(event->_callTraceId);
buf->put8(static_cast<int>(event->_observedBlockingState));
writeContextSnapshot(buf, event->_ctx);
writeEventSizePrefix(buf, start);
flushIfNeeded(buf);
}

void Recording::recordWallClockEpoch(Buffer *buf, WallClockEpochEvent *event) {
int start = buf->skip(1);
buf->putVar64(T_WALLCLOCK_SAMPLE_EPOCH);
Expand All @@ -1883,7 +1898,7 @@ void Recording::recordWallClockEpoch(Buffer *buf, WallClockEpochEvent *event) {
buf->putVar64(event->_num_failed_samples);
buf->putVar64(event->_num_exited_threads);
buf->putVar64(event->_num_permission_denied);
buf->putVar64(event->_num_suppressed_sampled_run);
buf->putVar64(event->_num_suppressed_owned_block);
writeEventSizePrefix(buf, start);
flushIfNeeded(buf);
}
Expand Down Expand Up @@ -2138,6 +2153,21 @@ void FlightRecorder::recordQueueTime(int lock_index, int tid,
}
}

bool FlightRecorder::recordTaskBlock(int lock_index, int tid,
TaskBlockEvent *event) {
OptionalSharedLockGuard locker(&_rec_lock);
if (locker.ownsLock()) {
Recording* rec = _rec;
if (rec != nullptr) {
Buffer *buf = rec->buffer(lock_index);
rec->addThread(lock_index, tid);
rec->recordTaskBlock(buf, tid, event);
return true;
}
}
return false;
}

void FlightRecorder::recordDatadogSetting(int lock_index, int length,
const char *name, const char *value,
const char *unit) {
Expand Down
2 changes: 2 additions & 0 deletions ddprof-lib/src/main/cpp/flightRecorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ class Recording {
void recordWallClockEpoch(Buffer *buf, WallClockEpochEvent *event);
void recordTraceRoot(Buffer *buf, int tid, TraceRootEvent *event);
void recordQueueTime(Buffer *buf, int tid, QueueTimeEvent *event);
void recordTaskBlock(Buffer *buf, int tid, TaskBlockEvent *event);
void recordAllocation(RecordingBuffer *buf, int tid, u64 call_trace_id,
AllocEvent *event);
void recordMallocSample(Buffer *buf, int tid, u64 call_trace_id,
Expand Down Expand Up @@ -424,6 +425,7 @@ class FlightRecorder {
void wallClockEpoch(int lock_index, WallClockEpochEvent *event);
void recordTraceRoot(int lock_index, int tid, TraceRootEvent *event);
void recordQueueTime(int lock_index, int tid, QueueTimeEvent *event);
bool recordTaskBlock(int lock_index, int tid, TaskBlockEvent *event);

bool active() const { return _rec != NULL; }

Expand Down
30 changes: 30 additions & 0 deletions ddprof-lib/src/main/cpp/frames.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
/*
* Copyright 2026 Datadog, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _FRAMES_H
#define _FRAMES_H

#include <jni.h>
#include <jvmti.h>
#include "vmEntry.h"

inline void copyJvmtiFrames(ASGCT_CallFrame *frames,
const jvmtiFrameInfo *jvmti_frames,
jint num_frames) {
// The source and destination commonly refer to the two views of the same
// CallTraceBuffer union. Read both source fields before either write.
for (jint i = 0; i < num_frames; ++i) {
jmethodID method = jvmti_frames[i].method;
jlocation location = jvmti_frames[i].location;
frames[i].method_id = method;
frames[i].bci = static_cast<jint>(location);
LP64_ONLY(frames[i].padding = 0;)
}
}

inline int makeFrame(ASGCT_CallFrame *frames, jint type, jmethodID id) {
frames[0].bci = type;
frames[0].method_id = id;
Expand Down
Loading
Loading