-
Notifications
You must be signed in to change notification settings - Fork 377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PROF-8667] Heap Profiling - Part 3 - Frees and Queue #3283
[PROF-8667] Heap Profiling - Part 3 - Frees and Queue #3283
Conversation
… alexjf/prof-8667-heap-profiling-part3-free-and-queue
… alexjf/prof-8667-heap-profiling-part3-free-and-queue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few notes!
@@ -143,6 +163,8 @@ heap_recorder* heap_recorder_new(void) { | |||
.obj = Qnil, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⬆️ I just noticed that for the recorder we're using xmalloc
instead of xcalloc
-- maybe worth using xcalloc
? Just in case we forget to initialize something at some point and we get a more sane default.
if (error) { | ||
// unhappy and hopefully rare path | ||
if (error == EBUSY) { | ||
// We weren't able to get a lock | ||
// TODO: Add some queuing system so we can do something other than drop this data. | ||
// We weren't able to get a lock, enqueue it for later processing | ||
// When enqueueing, always use a new stack, we can't guarantee a reference to a shared one | ||
// won't be cleared in-between due to processing of a free. | ||
// We could potentially improve this but this is not supposed to be the critical path anyway. | ||
heap_stack *stack = heap_stack_new(locations); | ||
enqueue_allocation(heap_recorder, stack, new_obj, active_recording->object_data); | ||
} else { | ||
// Something unexpected happened, lets error out | ||
ENFORCE_SUCCESS_GVL(error) | ||
} | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Maybe we could structure this as
if (error == EBUSY) {
// ... stuff
return;
}
if (error) ENFORCE_SUCCESS_GVL(error);
// Happy path goes here
to avoid the weird return
that's hanging after the else
but actually belongs to the if
side only ;)
if (object_record == NULL) { | ||
// we don't seem to be tracking this object on the table atm | ||
// check if the allocation sample is in the queue | ||
for (size_t i = 0; i < heap_recorder->queued_samples_len; i++) { | ||
uncommitted_sample *queued_sample = &heap_recorder->queued_samples[i]; | ||
if (queued_sample->obj == obj && !queued_sample->skip) { | ||
queued_sample->skip = true; | ||
break; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it's something we want/can do something at this point (or maybe this is another reason not to use the freeobj tracepoint), but I'm thinking this can have a potential downside in a case such as:
- The queue has a bunch of stuff to do
- Ruby starts a GC, so queue is not processed
- Ruby releases A LOT of objects, with in the extreme case none of them actually being tracked by us
- We need to go through the (potentially long) queue for every one of this objects
- Only after the GC do we process the queue
Replaced with #3328 |
2.0 Upgrade Guide notes
What does this PR do?
Motivation:
Additional Notes:
How to test the change?
For Datadog employees:
credentials of any kind, I've requested a review from
@DataDog/security-design-and-guidance
.Unsure? Have a question? Request a review!